PsychError SCREENComputer(void) { // const char *majorStructFieldNames[]={"macintosh", "windows", "osx" ,"linux", "kern", "hw", "processUserLongName", // "processUserShortName", "consoleUserName", "machineName", "localHostName", "location", "MACAddress", "system" }; const char *majorStructFieldNames[]={"macintosh", "windows", "osx" ,"linux", "MACAddress"}; const char *kernStructFieldNames[]={"ostype", "osrelease", "osrevision", "version","hostname"}; const char *hwStructFieldNames[]={"machine", "model", "ncpu", "physmem", "usermem", "busfreq", "cpufreq"}; int numMajorStructDimensions=1, numKernStructDimensions=1, numHwStructDimensions=1; int numMajorStructFieldNames=5, numKernStructFieldNames=5, numHwStructFieldNames=7; char ethernetMACStr[20]; struct ifreq devea; int s; PsychGenericScriptType *kernStruct, *hwStruct, *majorStruct; //all subfunctions should have these two lines PsychPushHelp(useString, synopsisString, seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; PsychErrorExit(PsychCapNumOutputArgs(1)); PsychErrorExit(PsychCapNumInputArgs(0)); //fill the major struct PsychAllocOutStructArray(1, FALSE, numMajorStructDimensions, numMajorStructFieldNames, majorStructFieldNames, &majorStruct); PsychSetStructArrayDoubleElement("macintosh", 0, 0, majorStruct); PsychSetStructArrayDoubleElement("windows", 0, 0, majorStruct); PsychSetStructArrayDoubleElement("linux", 0, 1, majorStruct); PsychSetStructArrayDoubleElement("osx", 0, 0, majorStruct); // Query hardware MAC address of primary ethernet interface: This is a unique id of the computer, // good enough to disambiguate our statistics: sprintf(ethernetMACStr, "00:00:00:00:00:00"); s = socket(PF_INET, SOCK_DGRAM, 0); if (s>=0) { strcpy(devea.ifr_name, "eth0"); if (ioctl(s, SIOCGIFHWADDR, &devea) >= 0) { sprintf(ethernetMACStr, "%.2X:%.2X:%.2X:%.2X:%.2X:%.2X", devea.ifr_ifru.ifru_hwaddr.sa_data[0]&0xff, devea.ifr_ifru.ifru_hwaddr.sa_data[1]&0xff, devea.ifr_ifru.ifru_hwaddr.sa_data[2]&0xff, devea.ifr_ifru.ifru_hwaddr.sa_data[3]&0xff, devea.ifr_ifru.ifru_hwaddr.sa_data[4]&0xff, devea.ifr_ifru.ifru_hwaddr.sa_data[5]&0xff); } close(s); } PsychSetStructArrayStringElement("MACAddress", 0, ethernetMACStr, majorStruct); return(PsychError_none); }
// M$-Windows implementation of Screen('Computer'): This is very rudimentary for now. // We only report the operating sytem type (="Windows") and MAC-Address, but don't report any more useful // information. MAC query does not work yet - We do not have the neccessary libraries to compile the code :( PsychError SCREENComputer(void) { // Info struct for queries to OS: OSVERSIONINFO osvi; char versionString[256]; // const char *majorStructFieldNames[]={"macintosh", "windows", "osx" ,"linux", "kern", "hw", "processUserLongName", // "processUserShortName", "consoleUserName", "machineName", "localHostName", "location", "MACAddress", "system" }; const char *majorStructFieldNames[]={"macintosh", "windows", "osx" ,"linux", "system", "IsVistaClass", "gstreamer", "supported"}; const char *kernStructFieldNames[]={"ostype", "osrelease", "osrevision", "version","hostname"}; const char *hwStructFieldNames[]={"machine", "model", "ncpu", "physmem", "usermem", "busfreq", "cpufreq"}; int numMajorStructDimensions=1, numKernStructDimensions=1, numHwStructDimensions=1; int numMajorStructFieldNames=8, numKernStructFieldNames=5, numHwStructFieldNames=7; PsychGenericScriptType *majorStruct; //all subfunctions should have these two lines PsychPushHelp(useString, synopsisString, seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; PsychErrorExit(PsychCapNumOutputArgs(1)); PsychErrorExit(PsychCapNumInputArgs(0)); //fill the major struct PsychAllocOutStructArray(1, FALSE, numMajorStructDimensions, numMajorStructFieldNames, majorStructFieldNames, &majorStruct); PsychSetStructArrayDoubleElement("macintosh", 0, 0, majorStruct); PsychSetStructArrayDoubleElement("windows", 0, 1, majorStruct); PsychSetStructArrayDoubleElement("linux", 0, 0, majorStruct); PsychSetStructArrayDoubleElement("osx", 0, 0, majorStruct); // Official support status: PsychSetStructArrayStringElement("supported", 0, (char*) PsychSupportStatus(), majorStruct); // GStreamer availability and rough version: #if defined(PTB_USE_GSTREAMER) #if GST_CHECK_VERSION(1,0,0) PsychSetStructArrayDoubleElement("gstreamer", 0, 1 * 10000 + 0 * 100 + 0, majorStruct); #else PsychSetStructArrayDoubleElement("gstreamer", 0, 0 * 10000 + 10 * 100 + 0, majorStruct); #endif #else PsychSetStructArrayDoubleElement("gstreamer", 0, 0, majorStruct); #endif // Query info about Windows version: versionString[0]=0; memset(&osvi, 0, sizeof(OSVERSIONINFO)); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&osvi); // Convert into string with major.minor.buildnumber - Name of service packs (max 128 chars) etc.: // Versions to products: 6.1 = Windows-7, 6.0 = Vista, 5.2 = Windows Server 2003, 5.1 = WindowsXP, 5.0 = Windows 2000, 4.x = NT sprintf(versionString, "NT-%i.%i.%i - %s", osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber, (char*) osvi.szCSDVersion); PsychSetStructArrayStringElement("system", 0, versionString, majorStruct); PsychSetStructArrayDoubleElement("IsVistaClass", 0, (PsychIsMSVista() ? 1 : 0), majorStruct); return(PsychError_none); }
PsychError PSYCHHIDGiveMeReports(void) { PsychGenericScriptType *outErr; const char *fieldNames[] = {"n", "name", "description"}; char *name = "", *description = ""; long error = 0; int deviceIndex; int reportBytes = 1024; PsychPushHelp(useString,synopsisString,seeAlsoString); if (PsychIsGiveHelp()) { PsychGiveHelp(); return(PsychError_none); }; PsychErrorExit(PsychCapNumOutputArgs(2)); PsychErrorExit(PsychCapNumInputArgs(2)); PsychCopyInIntegerArg(1,TRUE,&deviceIndex); PsychCopyInIntegerArg(2,false,&reportBytes); PsychHIDVerifyInit(); // Returns 1st return argument 'reports': error = GiveMeReports(deviceIndex,reportBytes); // PsychHIDReceiveReports.c // Return 2nd return argument 'err' struct: PsychHIDErrors(NULL, error, &name, &description); PsychAllocOutStructArray(2, kPsychArgOptional, -1, 3, fieldNames, &outErr); PsychSetStructArrayStringElement("name", 0, name, outErr); PsychSetStructArrayStringElement("description", 0, description, outErr); PsychSetStructArrayDoubleElement("n", 0, (double) error, outErr); return(PsychError_none); }
int PsychHIDReturnEventFromEventBuffer(int deviceIndex, int outArgIndex, double maxWaitTimeSecs) { unsigned int navail; PsychHIDEventRecord evt; PsychGenericScriptType *retevent; double* foo = NULL; const char *FieldNames[] = { "Time", "Pressed", "Keycode", "CookedKey" }; if (deviceIndex < 0) deviceIndex = PsychHIDGetDefaultKbQueueDevice(); if (!hidEventBuffer[deviceIndex]) return(0); PsychLockMutex(&hidEventBufferMutex[deviceIndex]); navail = hidEventBufferWritePos[deviceIndex] - hidEventBufferReadPos[deviceIndex]; // If nothing available and we're asked to wait for something, then wait: if ((navail == 0) && (maxWaitTimeSecs > 0)) { // Wait for something: PsychTimedWaitCondition(&hidEventBufferCondition[deviceIndex], &hidEventBufferMutex[deviceIndex], maxWaitTimeSecs); // Recompute number of available events: navail = hidEventBufferWritePos[deviceIndex] - hidEventBufferReadPos[deviceIndex]; } // Check if anything available, copy it if so: if (navail) { memcpy(&evt, &(hidEventBuffer[deviceIndex][hidEventBufferReadPos[deviceIndex] % hidEventBufferCapacity[deviceIndex]]), sizeof(PsychHIDEventRecord)); hidEventBufferReadPos[deviceIndex]++; } PsychUnlockMutex(&hidEventBufferMutex[deviceIndex]); if (navail) { // Return event struct: PsychAllocOutStructArray(outArgIndex, kPsychArgOptional, 1, 4, FieldNames, &retevent); PsychSetStructArrayDoubleElement("Time", 0, evt.timestamp, retevent); PsychSetStructArrayDoubleElement("Pressed", 0, (double) (evt.status & (1<<0)) ? 1 : 0, retevent); PsychSetStructArrayDoubleElement("Keycode", 0, (double) evt.rawEventCode, retevent); PsychSetStructArrayDoubleElement("CookedKey", 0, (double) evt.cookedEventCode, retevent); return(navail - 1); } else { // Return empty matrix: PsychCopyOutDoubleMatArg(outArgIndex, kPsychArgOptional, 0, 0, 0, foo); return(0); } }
PsychError PsychHIDEnumerateHIDInputDevices(int deviceClass) { const char *deviceFieldNames[]= {"usagePageValue", "usageValue", "usageName", "index", "transport", "vendorID", "productID", "version", "manufacturer", "product", "serialNumber", "locationID", "interfaceID", "totalElements", "features", "inputs", "outputs", "collections", "axes", "buttons", "hats", "sliders", "dials", "wheels" }; int numDeviceStructElements, numDeviceStructFieldNames=24, deviceIndex; PsychGenericScriptType *deviceStruct; dinfo *dev; int i; int numKeys, numAxis; char *type = ""; // Preparse: Count matching devices for deviceClass numDeviceStructElements = ndevices; // Alloc struct array of sufficient size: PsychAllocOutStructArray(1, kPsychArgOptional, numDeviceStructElements, numDeviceStructFieldNames, deviceFieldNames, &deviceStruct); deviceIndex = 0; // Return info: for(i = 0; i < ndevices; i++) { // Check i'th device: dev = &info[i]; switch(dev->dwDevType & 0xff) { case DI8DEVTYPE_MOUSE: case DI8DEVTYPE_SCREENPOINTER: type = "slave pointer"; if (dev->usagePage == 0) dev->usagePage = 1; if (dev->usageValue == 0) dev->usageValue = 2; break; case DI8DEVTYPE_KEYBOARD: type = "slave keyboard"; if (dev->usagePage == 0) dev->usagePage = 1; if (dev->usageValue == 0) dev->usageValue = 6; break; case DI8DEVTYPE_JOYSTICK: type = "slave joystick"; if (dev->usagePage == 0) dev->usagePage = 1; if (dev->usageValue == 0) dev->usageValue = 4; break; } PsychSetStructArrayDoubleElement("usagePageValue", deviceIndex, (double) dev->usagePage, deviceStruct); PsychSetStructArrayDoubleElement("usageValue", deviceIndex, (double) dev->usageValue, deviceStruct); PsychSetStructArrayStringElement("usageName", deviceIndex, type, deviceStruct); PsychSetStructArrayDoubleElement("index", deviceIndex, (double) i, deviceStruct); PsychSetStructArrayStringElement("transport", deviceIndex, dev->tszInstanceName, deviceStruct); PsychSetStructArrayStringElement("product", deviceIndex, dev->tszProductName, deviceStruct); PsychSetStructArrayDoubleElement("locationID", deviceIndex, (double) -1, deviceStruct); PsychSetStructArrayDoubleElement("interfaceID", deviceIndex, (double) -1, deviceStruct); PsychSetStructArrayDoubleElement("productID", deviceIndex, (double) -1, deviceStruct); //PsychSetStructArrayDoubleElement("vendorID", deviceIndex, (double)currentDevice->vendorID, deviceStruct); //PsychSetStructArrayDoubleElement("version", deviceIndex, (double)currentDevice->version, deviceStruct); //PsychSetStructArrayStringElement("manufacturer", deviceIndex, currentDevice->manufacturer, deviceStruct); //PsychSetStructArrayStringElement("serialNumber", deviceIndex, currentDevice->serial, deviceStruct); numKeys = numAxis = 0; PsychSetStructArrayDoubleElement("totalElements", deviceIndex, (double) numKeys + numAxis, deviceStruct); PsychSetStructArrayDoubleElement("features", deviceIndex, (double) 0, deviceStruct); PsychSetStructArrayDoubleElement("inputs", deviceIndex, (double) numKeys + numAxis, deviceStruct); PsychSetStructArrayDoubleElement("outputs", deviceIndex, (double) 0, deviceStruct); PsychSetStructArrayDoubleElement("collections", deviceIndex, (double) 0, deviceStruct); PsychSetStructArrayDoubleElement("axes", deviceIndex, (double) numAxis, deviceStruct); PsychSetStructArrayDoubleElement("buttons", deviceIndex, (double) numKeys, deviceStruct); PsychSetStructArrayDoubleElement("hats", deviceIndex, (double) 0, deviceStruct); PsychSetStructArrayDoubleElement("sliders", deviceIndex, (double) 0, deviceStruct); PsychSetStructArrayDoubleElement("dials", deviceIndex, (double) 0, deviceStruct); PsychSetStructArrayDoubleElement("wheels", deviceIndex, (double) 0, deviceStruct); deviceIndex++; } return(PsychError_none); }
PsychError SCREENComputer(void) { const char *majorStructFieldNames[]={"macintosh", "windows", "osx" ,"linux", "kern", "hw", "processUserLongName", "processUserShortName", "consoleUserName", "machineName", "localHostName", "location", "MACAddress", "system" }; const char *kernStructFieldNames[]={"ostype", "osrelease", "osrevision", "version","hostname"}; const char *hwStructFieldNames[]={"machine", "model", "ncpu", "physmem", "usermem", "busfreq", "cpufreq"}; int numMajorStructDimensions=1, numKernStructDimensions=1, numHwStructDimensions=1; int numMajorStructFieldNames=14, numKernStructFieldNames=5, numHwStructFieldNames=7; PsychGenericScriptType *kernStruct, *hwStruct, *majorStruct; //char tempStr[CTL_MAXNAME]; //this seems like a bug in Darwin, CTL_MAXNAME is shorter than the longest name. char tempStr[256], *ethernetMACStr; size_t tempIntSize, tempStrSize, tempULongIntSize; int mib[2]; int tempInt; unsigned long int tempULongInt; char *tempStrPtr; CFStringRef tempCFStringRef; psych_bool stringSuccess; int stringLengthChars, ethernetMACStrSizeBytes; long gestaltResult; OSErr gestaltError; // Str255 systemVersionStr, systemVersionStrForward; int i,strIndex, bcdDigit, lengthSystemVersionString; long osMajor, osMinor, osBugfix; char systemVersionStr[256]; //all subfunctions should have these two lines PsychPushHelp(useString, synopsisString, seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; PsychErrorExit(PsychCapNumOutputArgs(1)); PsychErrorExit(PsychCapNumInputArgs(0)); //fill the major struct PsychAllocOutStructArray(1, FALSE, numMajorStructDimensions, numMajorStructFieldNames, majorStructFieldNames, &majorStruct); PsychSetStructArrayDoubleElement("macintosh", 0, 0, majorStruct); PsychSetStructArrayDoubleElement("windows", 0, 0, majorStruct); PsychSetStructArrayDoubleElement("linux", 0, 0, majorStruct); PsychSetStructArrayDoubleElement("osx", 0, 1, majorStruct); //fill the kern struct and implant it within the major struct PsychAllocOutStructArray(-1, FALSE, numKernStructDimensions, numKernStructFieldNames, kernStructFieldNames, &kernStruct); mib[0]=CTL_KERN; mib[1]=KERN_OSTYPE; tempStrSize=sizeof(tempStr); ReportSysctlError(sysctl(mib, 2, tempStr, &tempStrSize, NULL, 0)); PsychSetStructArrayStringElement("ostype", 0, tempStr, kernStruct); mib[1]=KERN_OSRELEASE; tempStrSize=sizeof(tempStr); ReportSysctlError(sysctl(mib, 2, tempStr, &tempStrSize, NULL, 0)); PsychSetStructArrayStringElement("osrelease", 0, tempStr, kernStruct); mib[1]=KERN_OSREV; tempIntSize=sizeof(tempInt); ReportSysctlError(sysctl(mib, 2, &tempInt, &tempIntSize, NULL, 0)); PsychSetStructArrayDoubleElement("osrevision", 0, (double)tempInt, kernStruct); mib[1]=KERN_VERSION; tempStrSize=sizeof(tempStr); ReportSysctlError(sysctl(mib, 2, tempStr, &tempStrSize, NULL, 0)); PsychSetStructArrayStringElement("version", 0, tempStr, kernStruct); mib[1]=KERN_HOSTNAME; tempStrSize=sizeof(tempStr); ReportSysctlError(sysctl(mib, 2, tempStr, &tempStrSize, NULL, 0)); PsychSetStructArrayStringElement("hostname", 0, tempStr, kernStruct); PsychSetStructArrayStructElement("kern",0, kernStruct, majorStruct); //fill the hw struct and implant it within the major struct PsychAllocOutStructArray(-1, FALSE, numHwStructDimensions, numHwStructFieldNames, hwStructFieldNames, &hwStruct); mib[0]=CTL_HW; mib[1]=HW_MACHINE; tempStrSize=sizeof(tempStr); ReportSysctlError(sysctl(mib, 2, tempStr, &tempStrSize, NULL, 0)); PsychSetStructArrayStringElement("machine", 0, tempStr, hwStruct); mib[1]=HW_MODEL; tempStrSize=sizeof(tempStr); ReportSysctlError(sysctl(mib, 2, tempStr, &tempStrSize, NULL, 0)); PsychSetStructArrayStringElement("model", 0, tempStr, hwStruct); mib[1]=HW_NCPU; tempIntSize=sizeof(tempInt); ReportSysctlError(sysctl(mib, 2, &tempInt, &tempIntSize, NULL, 0)); PsychSetStructArrayDoubleElement("ncpu", 0, (double)tempInt, hwStruct); mib[1]=HW_MEMSIZE; long long tempLongInt; tempULongIntSize=sizeof(tempLongInt); ReportSysctlError(sysctl(mib, 2, &tempLongInt, &tempULongIntSize, NULL, 0)); PsychSetStructArrayDoubleElement("physmem", 0, (double)tempLongInt, hwStruct); mib[1]=HW_USERMEM; tempULongIntSize=sizeof(tempULongInt); ReportSysctlError(sysctl(mib, 2, &tempULongInt, &tempULongIntSize, NULL, 0)); PsychSetStructArrayDoubleElement("usermem", 0, (double)tempULongInt, hwStruct); mib[1]=HW_BUS_FREQ; tempULongIntSize=sizeof(tempULongInt); ReportSysctlError(sysctl(mib, 2, &tempULongInt, &tempULongIntSize, NULL, 0)); PsychSetStructArrayDoubleElement("busfreq", 0, (double)tempULongInt, hwStruct); mib[1]=HW_CPU_FREQ; tempULongIntSize=sizeof(tempULongInt); ReportSysctlError(sysctl(mib, 2, &tempULongInt, &tempULongIntSize, NULL, 0)); PsychSetStructArrayDoubleElement("cpufreq", 0, (double)tempULongInt, hwStruct); PsychSetStructArrayStructElement("hw",0, hwStruct, majorStruct); //fill in the process user, console user and machine name in the root struct. tempCFStringRef= CSCopyMachineName(); if (tempCFStringRef) { stringLengthChars=(int) CFStringGetMaximumSizeForEncoding(CFStringGetLength(tempCFStringRef), kCFStringEncodingUTF8); tempStrPtr=malloc(sizeof(char) * (stringLengthChars+1)); stringSuccess= CFStringGetCString(tempCFStringRef, tempStrPtr, stringLengthChars+1, kCFStringEncodingUTF8); if(stringSuccess) { PsychSetStructArrayStringElement("machineName", 0, tempStrPtr, majorStruct); } else { PsychSetStructArrayStringElement("machineName", 0, "UNKNOWN! QUERY FAILED DUE TO EMPTY OR PROBLEMATIC NAME.", majorStruct); } free(tempStrPtr); CFRelease(tempCFStringRef); } else { PsychSetStructArrayStringElement("machineName", 0, "UNKNOWN! QUERY FAILED DUE TO EMPTY OR PROBLEMATIC NAME.", majorStruct); } tempCFStringRef= CSCopyUserName(TRUE); //use short name if (tempCFStringRef) { stringLengthChars=(int) CFStringGetMaximumSizeForEncoding(CFStringGetLength(tempCFStringRef), kCFStringEncodingUTF8); tempStrPtr=malloc(sizeof(char) * (stringLengthChars+1)); stringSuccess= CFStringGetCString(tempCFStringRef, tempStrPtr, stringLengthChars+1, kCFStringEncodingUTF8); if(stringSuccess) { PsychSetStructArrayStringElement("processUserShortName", 0, tempStrPtr, majorStruct); } else { PsychSetStructArrayStringElement("processUserShortName", 0, "UNKNOWN! QUERY FAILED DUE TO EMPTY OR PROBLEMATIC NAME.", majorStruct); } free(tempStrPtr); CFRelease(tempCFStringRef); } else { PsychSetStructArrayStringElement("processUserShortName", 0, "UNKNOWN! QUERY FAILED DUE TO EMPTY OR PROBLEMATIC NAME.", majorStruct); } tempCFStringRef= CSCopyUserName(FALSE); //use long name if (tempCFStringRef) { stringLengthChars=(int) CFStringGetMaximumSizeForEncoding(CFStringGetLength(tempCFStringRef), kCFStringEncodingUTF8); tempStrPtr=malloc(sizeof(char) * (stringLengthChars+1)); stringSuccess= CFStringGetCString(tempCFStringRef, tempStrPtr, stringLengthChars+1, kCFStringEncodingUTF8); if(stringSuccess) { PsychSetStructArrayStringElement("processUserLongName", 0, tempStrPtr, majorStruct); } else { PsychSetStructArrayStringElement("processUserLongName", 0, "UNKNOWN! QUERY FAILED DUE TO EMPTY OR PROBLEMATIC NAME.", majorStruct); } free(tempStrPtr); CFRelease(tempCFStringRef); } else { PsychSetStructArrayStringElement("processUserLongName", 0, "UNKNOWN! QUERY FAILED DUE TO EMPTY OR PROBLEMATIC NAME.", majorStruct); } tempCFStringRef= SCDynamicStoreCopyConsoleUser(NULL, NULL, NULL); if (tempCFStringRef) { stringLengthChars=(int) CFStringGetMaximumSizeForEncoding(CFStringGetLength(tempCFStringRef), kCFStringEncodingUTF8); tempStrPtr=malloc(sizeof(char) * (stringLengthChars+1)); stringSuccess= CFStringGetCString(tempCFStringRef, tempStrPtr, stringLengthChars+1, kCFStringEncodingUTF8); if(stringSuccess) { PsychSetStructArrayStringElement("consoleUserName", 0, tempStrPtr, majorStruct); } else { PsychSetStructArrayStringElement("consoleUserName", 0, "UNKNOWN! QUERY FAILED DUE TO EMPTY OR PROBLEMATIC NAME.", majorStruct); } free(tempStrPtr); CFRelease(tempCFStringRef); } else { PsychSetStructArrayStringElement("consoleUserName", 0, "UNKNOWN! QUERY FAILED DUE TO EMPTY OR PROBLEMATIC NAME.", majorStruct); } tempCFStringRef= SCDynamicStoreCopyLocalHostName(NULL); if (tempCFStringRef) { stringLengthChars=(int) CFStringGetMaximumSizeForEncoding(CFStringGetLength(tempCFStringRef), kCFStringEncodingUTF8); tempStrPtr=malloc(sizeof(char) * (stringLengthChars+1)); stringSuccess= CFStringGetCString(tempCFStringRef, tempStrPtr, stringLengthChars+1, kCFStringEncodingUTF8); if(stringSuccess) { PsychSetStructArrayStringElement("localHostName", 0, tempStrPtr, majorStruct); } else { PsychSetStructArrayStringElement("localHostName", 0, "UNKNOWN! QUERY FAILED DUE TO EMPTY OR PROBLEMATIC NAME.", majorStruct); } free(tempStrPtr); CFRelease(tempCFStringRef); } else { PsychSetStructArrayStringElement("localHostName", 0, "UNKNOWN! QUERY FAILED DUE TO EMPTY OR PROBLEMATIC NAME.", majorStruct); } tempCFStringRef= SCDynamicStoreCopyLocation(NULL); if (tempCFStringRef) { stringLengthChars=(int) CFStringGetMaximumSizeForEncoding(CFStringGetLength(tempCFStringRef), kCFStringEncodingUTF8); tempStrPtr=malloc(sizeof(char) * (stringLengthChars+1)); stringSuccess= CFStringGetCString(tempCFStringRef, tempStrPtr, stringLengthChars+1, kCFStringEncodingUTF8); if(stringSuccess) { PsychSetStructArrayStringElement("location", 0, tempStrPtr, majorStruct); } else { PsychSetStructArrayStringElement("location", 0, "UNKNOWN! QUERY FAILED DUE TO EMPTY OR PROBLEMATIC NAME.", majorStruct); } free(tempStrPtr); CFRelease(tempCFStringRef); } else { PsychSetStructArrayStringElement("location", 0, "UNKNOWN! QUERY FAILED DUE TO EMPTY OR PROBLEMATIC NAME.", majorStruct); } //Add the ethernet MAC address of the primary ethernet interface to the stuct. This can serve as a unique identifier for the computer. ethernetMACStrSizeBytes=GetPrimaryEthernetAddressStringLengthBytes(TRUE)+1; ethernetMACStr=(char*) malloc(sizeof(char) * ethernetMACStrSizeBytes); GetPrimaryEthernetAddressString(ethernetMACStr, TRUE, TRUE); PsychSetStructArrayStringElement("MACAddress", 0, ethernetMACStr, majorStruct); free(ethernetMACStr); //Add the system version string: Gestalt(gestaltSystemVersionMajor, &osMajor); Gestalt(gestaltSystemVersionMinor, &osMinor); Gestalt(gestaltSystemVersionBugFix, &osBugfix); sprintf(systemVersionStr, "Mac OS %i.%i.%i", osMajor, osMinor, osBugfix); //embed it in the return struct PsychSetStructArrayStringElement("system", 0, systemVersionStr, majorStruct); /* OLD DEAD Implementation, left for now as a reference... //Add the system version string: gestaltError=Gestalt(gestaltSystemVersion, &gestaltResult); //The result is a four-digit value stored in BCD in the lower 16-bits of the result. There are implicit decimal // points between the last three digis. For example Mac OS 10.3.6 is: // // 0000 0000 0000 0000 0001 0000 0011 0110 // 1 0 3 6 // 1 0. 3. 6 strIndex=0; //4th digit. bcdDigit=gestaltResult & 15; gestaltResult= gestaltResult>>4; strIndex=strIndex+sprintf(systemVersionStr+strIndex, "%i", bcdDigit); //decimal point strIndex=strIndex+sprintf(systemVersionStr+strIndex, "%s", "."); //3rd digit bcdDigit=gestaltResult & 15; gestaltResult= gestaltResult>>4; strIndex=strIndex+sprintf(systemVersionStr+strIndex, "%i", bcdDigit); //decimal point strIndex=strIndex+sprintf(systemVersionStr+strIndex, "%s", "."); //second digit //2nd digit. bcdDigit=gestaltResult & 15; gestaltResult= gestaltResult>>4; strIndex=strIndex+sprintf(systemVersionStr+strIndex, "%i", bcdDigit); //1st digit bcdDigit=gestaltResult & 15; gestaltResult= gestaltResult>>4; strIndex=strIndex+sprintf(systemVersionStr+strIndex, "%i", bcdDigit); //preface with "Mac OS " strIndex=strIndex+sprintf(systemVersionStr+strIndex, "%s", " SO caM"); //reverse to make it forward lengthSystemVersionString=strlen(systemVersionStr); for(i=0;i<lengthSystemVersionString;i++){ systemVersionStrForward[lengthSystemVersionString-1-i]=systemVersionStr[i]; } systemVersionStrForward[lengthSystemVersionString]='\0'; //embed it in the return struct PsychSetStructArrayStringElement("system", 0, systemVersionStrForward, majorStruct); */ return(PsychError_none); }
// M$-Windows implementation of Screen('Computer'): This is very rudimentary for now. // We only report the operating sytem type (="Windows") and MAC-Address, but don't report any more useful // information. MAC query does not work yet - We do not have the neccessary libraries to compile the code :( PsychError SCREENComputer(void) { // Info struct for queries to OS: OSVERSIONINFO osvi; char versionString[256]; // const char *majorStructFieldNames[]={"macintosh", "windows", "osx" ,"linux", "kern", "hw", "processUserLongName", // "processUserShortName", "consoleUserName", "machineName", "localHostName", "location", "MACAddress", "system" }; const char *majorStructFieldNames[]={"macintosh", "windows", "osx" ,"linux", "system", "MACAddress"}; const char *kernStructFieldNames[]={"ostype", "osrelease", "osrevision", "version","hostname"}; const char *hwStructFieldNames[]={"machine", "model", "ncpu", "physmem", "usermem", "busfreq", "cpufreq"}; int numMajorStructDimensions=1, numKernStructDimensions=1, numHwStructDimensions=1; int numMajorStructFieldNames=5, numKernStructFieldNames=5, numHwStructFieldNames=7; // char ethernetMACStr[20]; // unsigned char MACData[6]; // UUID uuid; int i; PsychGenericScriptType *kernStruct, *hwStruct, *majorStruct; //all subfunctions should have these two lines PsychPushHelp(useString, synopsisString, seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; PsychErrorExit(PsychCapNumOutputArgs(1)); PsychErrorExit(PsychCapNumInputArgs(0)); //fill the major struct PsychAllocOutStructArray(1, FALSE, numMajorStructDimensions, numMajorStructFieldNames, majorStructFieldNames, &majorStruct); PsychSetStructArrayDoubleElement("macintosh", 0, 0, majorStruct); PsychSetStructArrayDoubleElement("windows", 0, 1, majorStruct); PsychSetStructArrayDoubleElement("linux", 0, 0, majorStruct); PsychSetStructArrayDoubleElement("osx", 0, 0, majorStruct); // Query info about Windows version: versionString[0]=0; memset(&osvi, 0, sizeof(OSVERSIONINFO)); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&osvi); // Convert into string with major.minor.buildnumber - Name of service packs (max 128 chars) etc.: // Versions to products: 6.1 = Windows-7, 6.0 = Vista, 5.2 = Windows Server 2003, 5.1 = WindowsXP, 5.0 = Windows 2000, 4.x = NT sprintf(versionString, "%i.%i.%i - %s", osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber, (char*) osvi.szCSDVersion); PsychSetStructArrayStringElement("system", 0, versionString, majorStruct); // Query hardware MAC address of primary ethernet interface: This is a unique id of the computer, // good enough to disambiguate our statistics: // sprintf(ethernetMACStr, "00:00:00:00:00:00"); // Ask OS to create UUID. Windows uses the MAC address of primary interface // in bytes 2 to 7 to do this: //UuidCreateSequential( &uuid ); // Ask OS to create UUID //for (i=2; i<8; i++) MACData[i - 2] = uuid.Data4[i]; //sprintf(ethernetMACStr, "%.2X:%.2X:%.2X:%.2X:%.2X:%.2X", // MACData[0] & 0xff, MACData[1] & 0xff, // MACData[2] & 0xff, MACData[3] & 0xff, // MACData[4] & 0xff, MACData[5] & 0xff); // PsychSetStructArrayStringElement("MACAddress", 0, ethernetMACStr, majorStruct); 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 SCREENGetWindowInfo(void) { const char *FieldNames[]={ "Beamposition", "LastVBLTimeOfFlip", "LastVBLTime", "VBLCount", "TimeAtSwapRequest", "TimePostSwapRequest", "RawSwapTimeOfFlip", "VBLTimePostFlip", "OSSwapTimestamp", "GPULastFrameRenderTime", "StereoMode", "ImagingMode", "MultiSampling", "MissedDeadlines", "FlipCount", "StereoDrawBuffer", "GuesstimatedMemoryUsageMB", "VBLStartline", "VBLEndline", "VideoRefreshFromBeamposition", "GLVendor", "GLRenderer", "GLVersion", "GPUCoreId", "GLSupportsFBOUpToBpc", "GLSupportsBlendingUpToBpc", "GLSupportsTexturesUpToBpc", "GLSupportsFilteringUpToBpc", "GLSupportsPrecisionColors", "GLSupportsFP32Shading", "BitsPerColorComponent", "IsFullscreen", "SpecialFlags", "SwapGroup", "SwapBarrier" }; const int fieldCount = 35; PsychGenericScriptType *s; PsychWindowRecordType *windowRecord; double beamposition, lastvbl; int infoType = 0, retIntArg; double auxArg1, auxArg2, auxArg3; CGDirectDisplayID displayId; psych_uint64 postflip_vblcount; double vbl_startline; long scw, sch; psych_bool onscreen; //all subfunctions should have these two lines. PsychPushHelp(useString, synopsisString, seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; PsychErrorExit(PsychCapNumInputArgs(5)); //The maximum number of inputs PsychErrorExit(PsychRequireNumInputArgs(1)); //The required number of inputs PsychErrorExit(PsychCapNumOutputArgs(1)); //The maximum number of outputs // Query infoType flag: Defaults to zero. PsychCopyInIntegerArg(2, FALSE, &infoType); if (infoType < 0 || infoType > 5) PsychErrorExitMsg(PsychError_user, "Invalid 'infoType' argument specified! Valid are 0, 1, 2, 3, 4 and 5."); // Windowserver info requested? if (infoType == 2 || infoType == 3) { // Return info about WindowServer: #if PSYCH_SYSTEM == PSYCH_OSX const char *CoreGraphicsFieldNames[]={ "CGSFps", "CGSValue1", "CGSValue2", "CGSValue3", "CGSDebugOptions" }; const int CoreGraphicsFieldCount = 5; float cgsFPS, val1, val2, val3; // This (undocumented) Apple call retrieves information about performance statistics of // the Core graphics server, also known as WindowServer or Quartz compositor: CGSGetPerformanceData(_CGSDefaultConnection(), &cgsFPS, &val1, &val2, &val3); if (CGSGetDebugOptions(&retIntArg)) { if (PsychPrefStateGet_Verbosity() > 1) printf("PTB-WARNING: GetWindowInfo: Call to CGSGetDebugOptions() failed!\n"); } PsychAllocOutStructArray(1, FALSE, 1, CoreGraphicsFieldCount, CoreGraphicsFieldNames, &s); PsychSetStructArrayDoubleElement("CGSFps", 0 , cgsFPS, s); PsychSetStructArrayDoubleElement("CGSValue1", 0, val1, s); PsychSetStructArrayDoubleElement("CGSValue2", 0, val2, s); PsychSetStructArrayDoubleElement("CGSValue3", 0, val3, s); PsychSetStructArrayDoubleElement("CGSDebugOptions", 0, (double) retIntArg, s); if ( (infoType == 3) && PsychCopyInDoubleArg(3, FALSE, &auxArg1) ) { // Type 3 setup request with auxArg1 provided. Apple auxArg1 as debugFlag setting // for the CoreGraphics server: DANGEROUS! if (CGSSetDebugOptions((unsigned int) auxArg1)) { if (PsychPrefStateGet_Verbosity() > 1) printf("PTB-WARNING: GetWindowInfo: Call to CGSSetDebugOptions() failed!\n"); } } #endif #if PSYCH_SYSTEM == PSYCH_WINDOWS psych_uint64 onsetVBLCount, frameId; double onsetVBLTime, compositionRate; psych_uint64 targetVBL; PsychAllocInWindowRecordArg(kPsychUseDefaultArgPosition, TRUE, &windowRecord); // Query all DWM presentation timing info, return full info as struct in optional return argument '1': if (PsychOSGetPresentationTimingInfo(windowRecord, TRUE, 0, &onsetVBLCount, &onsetVBLTime, &frameId, &compositionRate, 1)) { // Query success: Info struct has been created and returned by PsychOSGetPresentationTimingInfo()... auxArg1 = auxArg2 = 0; auxArg3 = 2; // Want us to change settings? if ( (infoType == 3) && PsychCopyInDoubleArg(3, FALSE, &auxArg1) && PsychCopyInDoubleArg(4, FALSE, &auxArg2) && PsychCopyInDoubleArg(5, FALSE, &auxArg3)) { if (auxArg1 < 0) auxArg1 = 0; targetVBL = auxArg1; if (PsychOSSetPresentParameters(windowRecord, targetVBL, (int) auxArg3, auxArg2)) { if (PsychPrefStateGet_Verbosity() > 5) printf("PTB-DEBUG: GetWindowInfo: Call to PsychOSSetPresentParameters(%i, %i, %f) SUCCESS!\n", (int) auxArg1, (int) auxArg3, auxArg2); } else { if (PsychPrefStateGet_Verbosity() > 1) printf("PTB-WARNING: GetWindowInfo: Call to PsychOSSetPresentParameters() failed!\n"); } } } else { // Unsupported / Failed: PsychCopyOutDoubleArg(1, FALSE, -1); } #endif #if PSYCH_SYSTEM == PSYCH_LINUX if (infoType == 2) { // MMIO register Read for screenid "auxArg1", register offset "auxArg2": PsychCopyInDoubleArg(3, TRUE, &auxArg1); PsychCopyInDoubleArg(4, TRUE, &auxArg2); PsychCopyOutDoubleArg(1, FALSE, (double) PsychOSKDReadRegister((int) auxArg1, (unsigned int) auxArg2, NULL)); } if (infoType == 3) { // MMIO register Write for screenid "auxArg1", register offset "auxArg2", to value "auxArg3": PsychCopyInDoubleArg(3, TRUE, &auxArg1); PsychCopyInDoubleArg(4, TRUE, &auxArg2); PsychCopyInDoubleArg(5, TRUE, &auxArg3); PsychOSKDWriteRegister((int) auxArg1, (unsigned int) auxArg2, (unsigned int) auxArg3, NULL); } #endif // Done. return(PsychError_none); } // Get the window record: PsychAllocInWindowRecordArg(kPsychUseDefaultArgPosition, TRUE, &windowRecord); onscreen = PsychIsOnscreenWindow(windowRecord); if (onscreen) { // Query rasterbeam position: Will return -1 if unsupported. PsychGetCGDisplayIDFromScreenNumber(&displayId, windowRecord->screenNumber); beamposition = (double) PsychGetDisplayBeamPosition(displayId, windowRecord->screenNumber); } else { beamposition = -1; } if (infoType == 1) { // Return the measured beamposition: PsychCopyOutDoubleArg(1, FALSE, beamposition); } else if (infoType == 4) { // Return async flip state: 1 = Active, 0 = Inactive. PsychCopyOutDoubleArg(1, FALSE, (((NULL != windowRecord->flipInfo) && (0 != windowRecord->flipInfo->asyncstate)) ? 1 : 0)); } else if (infoType == 5) { // Create a GL_EXT_timer_query object for this window: if (glewIsSupported("GL_EXT_timer_query")) { // Pending queries finished? if (windowRecord->gpuRenderTimeQuery > 0) { PsychErrorExitMsg(PsychError_user, "Tried to create a new GPU rendertime query, but last query not yet finished! Call Screen('Flip') first!"); } // Enable our rendering context by selecting this window as drawing target: PsychSetDrawingTarget(windowRecord); // Generate Query object: glGenQueries(1, &windowRecord->gpuRenderTimeQuery); // Emit Query: GPU will measure elapsed processing time in Nanoseconds, starting // with the first GL command executed after this command: glBeginQuery(GL_TIME_ELAPSED_EXT, windowRecord->gpuRenderTimeQuery); // Reset last measurement: windowRecord->gpuRenderTime = 0; } else { if (PsychPrefStateGet_Verbosity() > 4) printf("PTB-INFO: GetWindowInfo for infoType 5: GPU timer query objects are unsupported on this platform and GPU. Call ignored!\n"); } } else { // Return all information: PsychAllocOutStructArray(1, FALSE, 1, fieldCount, FieldNames, &s); // Rasterbeam position: PsychSetStructArrayDoubleElement("Beamposition", 0, beamposition, s); // Time of last vertical blank when a double-buffer swap occured: if ((windowRecord->flipCount > 0) && (windowRecord->time_at_last_vbl == 0) && (PsychPrefStateGet_VBLTimestampingMode() == 4)) { // If time_at_last_vbl for an already finished or at least pending flip isn't available and // we have support for OS-Builtin timestamping enabled, we try to employ OS-Builtin timestamping // to get a timestamp for the most recent pending or finished flip. If this fails or is unsupported, // it will have no effect: PsychOSGetSwapCompletionTimestamp(windowRecord, 0, &(windowRecord->time_at_last_vbl)); } // Return it - or the value zero if it is (still) undefined/unavailable: PsychSetStructArrayDoubleElement("LastVBLTimeOfFlip", 0, windowRecord->time_at_last_vbl, s); // Uncorrected timestamp of flip swap completion: PsychSetStructArrayDoubleElement("RawSwapTimeOfFlip", 0, windowRecord->rawtime_at_swapcompletion, s); // Timestamp immediately prior to call to PsychOSFlipWindowBuffers(), i.e., time at swap request submission: PsychSetStructArrayDoubleElement("TimeAtSwapRequest", 0, windowRecord->time_at_swaprequest, s); // Timestamp immediately after call to PsychOSFlipWindowBuffers() returns, i.e., time at swap request submission completion: PsychSetStructArrayDoubleElement("TimePostSwapRequest", 0, windowRecord->time_post_swaprequest, s); // Timestamp immediately after call to PsychOSFlipWindowBuffers() returns, i.e., time at swap request submission completion: PsychSetStructArrayDoubleElement("VBLTimePostFlip", 0, windowRecord->postflip_vbltimestamp, s); // Swap completion timestamp for most recently completed swap, according to OS-builtin PsychOSGetSwapCompletionTimestamp() method: PsychSetStructArrayDoubleElement("OSSwapTimestamp", 0, windowRecord->osbuiltin_swaptime, s); // Result from last GPU rendertime query as triggered by infoType 5: Zero if undefined. PsychSetStructArrayDoubleElement("GPULastFrameRenderTime", 0, windowRecord->gpuRenderTime, s); // Try to determine system time of last VBL on display, independent of any // flips / bufferswaps. lastvbl = -1; postflip_vblcount = 0; // On supported systems, we can query the OS for the system time of last VBL, so we can // use the most recent VBL timestamp as baseline for timing calculations, // instead of one far in the past. if (onscreen) { lastvbl = PsychOSGetVBLTimeAndCount(windowRecord, &postflip_vblcount); } // If we couldn't determine this information we just set lastvbl to the last known // vbl timestamp of last flip -- better than nothing... if (lastvbl < 0) lastvbl = windowRecord->time_at_last_vbl; PsychSetStructArrayDoubleElement("LastVBLTime", 0, lastvbl, s); PsychSetStructArrayDoubleElement("VBLCount", 0, (double) (psych_int64) postflip_vblcount, s); // Misc. window parameters: PsychSetStructArrayDoubleElement("StereoMode", 0, windowRecord->stereomode, s); PsychSetStructArrayDoubleElement("ImagingMode", 0, windowRecord->imagingMode, s); PsychSetStructArrayDoubleElement("SpecialFlags", 0, windowRecord->specialflags, s); PsychSetStructArrayDoubleElement("IsFullscreen", 0, (windowRecord->specialflags & kPsychIsFullscreenWindow) ? 1 : 0, s); PsychSetStructArrayDoubleElement("MultiSampling", 0, windowRecord->multiSample, s); PsychSetStructArrayDoubleElement("MissedDeadlines", 0, windowRecord->nr_missed_deadlines, s); PsychSetStructArrayDoubleElement("FlipCount", 0, windowRecord->flipCount, s); PsychSetStructArrayDoubleElement("StereoDrawBuffer", 0, windowRecord->stereodrawbuffer, s); PsychSetStructArrayDoubleElement("GuesstimatedMemoryUsageMB", 0, (double) windowRecord->surfaceSizeBytes / 1024 / 1024, s); PsychSetStructArrayDoubleElement("BitsPerColorComponent", 0, (double) windowRecord->bpc, s); // Query real size of the underlying display in order to define the vbl_startline: PsychGetScreenSize(windowRecord->screenNumber, &scw, &sch); vbl_startline = (double) sch; PsychSetStructArrayDoubleElement("VBLStartline", 0, vbl_startline, s); // And VBL endline: PsychSetStructArrayDoubleElement("VBLEndline", 0, windowRecord->VBL_Endline, s); // Video refresh interval duration from beamposition method: PsychSetStructArrayDoubleElement("VideoRefreshFromBeamposition", 0, windowRecord->ifi_beamestimate, s); // Swap group assignment and swap barrier assignment, if any: PsychSetStructArrayDoubleElement("SwapGroup", 0, windowRecord->swapGroup, s); PsychSetStructArrayDoubleElement("SwapBarrier", 0, windowRecord->swapBarrier, s); // Which basic GPU architecture is this? PsychSetStructArrayStringElement("GPUCoreId", 0, windowRecord->gpuCoreId, s); // FBO's supported, and how deep? if (windowRecord->gfxcaps & kPsychGfxCapFBO) { if (windowRecord->gfxcaps & kPsychGfxCapFPFBO32) { PsychSetStructArrayDoubleElement("GLSupportsFBOUpToBpc", 0, 32, s); } else if (windowRecord->gfxcaps & kPsychGfxCapFPFBO16) { PsychSetStructArrayDoubleElement("GLSupportsFBOUpToBpc", 0, 16, s); } else PsychSetStructArrayDoubleElement("GLSupportsFBOUpToBpc", 0, 8, s); } else { PsychSetStructArrayDoubleElement("GLSupportsFBOUpToBpc", 0, 0, s); } // How deep is alpha blending supported? if (windowRecord->gfxcaps & kPsychGfxCapFPBlend32) { PsychSetStructArrayDoubleElement("GLSupportsBlendingUpToBpc", 0, 32, s); } else if (windowRecord->gfxcaps & kPsychGfxCapFPBlend16) { PsychSetStructArrayDoubleElement("GLSupportsBlendingUpToBpc", 0, 16, s); } else PsychSetStructArrayDoubleElement("GLSupportsBlendingUpToBpc", 0, 8, s); // How deep is texture mapping supported? if (windowRecord->gfxcaps & kPsychGfxCapFPTex32) { PsychSetStructArrayDoubleElement("GLSupportsTexturesUpToBpc", 0, 32, s); } else if (windowRecord->gfxcaps & kPsychGfxCapFPTex16) { PsychSetStructArrayDoubleElement("GLSupportsTexturesUpToBpc", 0, 16, s); } else PsychSetStructArrayDoubleElement("GLSupportsTexturesUpToBpc", 0, 8, s); // How deep is texture filtering supported? if (windowRecord->gfxcaps & kPsychGfxCapFPFilter32) { PsychSetStructArrayDoubleElement("GLSupportsFilteringUpToBpc", 0, 32, s); } else if (windowRecord->gfxcaps & kPsychGfxCapFPFilter16) { PsychSetStructArrayDoubleElement("GLSupportsFilteringUpToBpc", 0, 16, s); } else PsychSetStructArrayDoubleElement("GLSupportsFilteringUpToBpc", 0, 8, s); if (windowRecord->gfxcaps & kPsychGfxCapVCGood) { PsychSetStructArrayDoubleElement("GLSupportsPrecisionColors", 0, 1, s); } else PsychSetStructArrayDoubleElement("GLSupportsPrecisionColors", 0, 0, s); if (windowRecord->gfxcaps & kPsychGfxCapFP32Shading) { PsychSetStructArrayDoubleElement("GLSupportsFP32Shading", 0, 1, s); } else PsychSetStructArrayDoubleElement("GLSupportsFP32Shading", 0, 0, s); // Renderer information: This comes last, and would fail if async flips // are active, because it needs PsychSetDrawingTarget, which in turn needs async // flips to be inactive: PsychSetDrawingTarget(windowRecord); PsychSetStructArrayStringElement("GLVendor", 0, (char*) glGetString(GL_VENDOR), s); PsychSetStructArrayStringElement("GLRenderer", 0, (char*) glGetString(GL_RENDERER), s); PsychSetStructArrayStringElement("GLVersion", 0, (char*) glGetString(GL_VERSION), s); } // Done. return(PsychError_none); }
PsychError SCREENComputer(void) { // const char *majorStructFieldNames[]={"macintosh", "windows", "osx" ,"linux", "kern", "hw", "processUserLongName", // "processUserShortName", "consoleUserName", "machineName", "localHostName", "location", "MACAddress", "system" }; const char *majorStructFieldNames[]={"macintosh", "windows", "osx" ,"linux", "kern", "hw", "system", "machineName", "localHostName", "MACAddress", "gstreamer", "supported"}; const char *kernStructFieldNames[]={"ostype", "osrelease", "osrevision", "version","hostname"}; const char *hwStructFieldNames[]={"machine", "model", "ncpu", "physmem", "usermem", "busfreq", "cpufreq"}; int numMajorStructDimensions=-1, numKernStructDimensions=-1, numHwStructDimensions=-1; int numMajorStructFieldNames=12, numKernStructFieldNames=5, numHwStructFieldNames=7; char ethernetMACStr[20]; struct ifreq devea; int s, i; PsychGenericScriptType *kernStruct, *hwStruct, *majorStruct; struct utsname unameresult; char tmpString[1024]; //all subfunctions should have these two lines PsychPushHelp(useString, synopsisString, seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; PsychErrorExit(PsychCapNumOutputArgs(1)); PsychErrorExit(PsychCapNumInputArgs(0)); //fill the major struct PsychAllocOutStructArray(1, FALSE, numMajorStructDimensions, numMajorStructFieldNames, majorStructFieldNames, &majorStruct); PsychSetStructArrayDoubleElement("macintosh", 0, 0, majorStruct); PsychSetStructArrayDoubleElement("windows", 0, 0, majorStruct); PsychSetStructArrayDoubleElement("linux", 0, 1, majorStruct); PsychSetStructArrayDoubleElement("osx", 0, 0, majorStruct); // Official support status: PsychSetStructArrayStringElement("supported", 0, (char*) PsychSupportStatus(), majorStruct); // GStreamer availability and rough version: #if defined(PTB_USE_GSTREAMER) #if GST_CHECK_VERSION(1,0,0) PsychSetStructArrayDoubleElement("gstreamer", 0, 1 * 10000 + 0 * 100 + 0, majorStruct); #else PsychSetStructArrayDoubleElement("gstreamer", 0, 0 * 10000 + 10 * 100 + 0, majorStruct); #endif #else PsychSetStructArrayDoubleElement("gstreamer", 0, 0, majorStruct); #endif // Query hardware MAC address of primary ethernet interface: This is a unique id of the computer, // good enough to disambiguate our statistics: sprintf(ethernetMACStr, "00:00:00:00:00:00"); s = socket(PF_INET, SOCK_DGRAM, 0); if (s >= 0) { // Probe eth0 to eth99 for a valid network interface: for (i = 0; i < 100; i++) { sprintf(devea.ifr_name, "eth%d", i); if (ioctl(s, SIOCGIFHWADDR, &devea) >= 0) { // Success: Use its MAC address and be done: sprintf(ethernetMACStr, "%.2X:%.2X:%.2X:%.2X:%.2X:%.2X", devea.ifr_ifru.ifru_hwaddr.sa_data[0]&0xff, devea.ifr_ifru.ifru_hwaddr.sa_data[1]&0xff, devea.ifr_ifru.ifru_hwaddr.sa_data[2]&0xff, devea.ifr_ifru.ifru_hwaddr.sa_data[3]&0xff, devea.ifr_ifru.ifru_hwaddr.sa_data[4]&0xff, devea.ifr_ifru.ifru_hwaddr.sa_data[5]&0xff); break; } } close(s); } PsychSetStructArrayStringElement("MACAddress", 0, ethernetMACStr, majorStruct); uname(&unameresult); sprintf(tmpString, "Linux %s", unameresult.release); PsychSetStructArrayStringElement("system", 0, tmpString, majorStruct); // Fill the kern struct and implant it within the major struct PsychAllocOutStructArray(-1, FALSE, numKernStructDimensions, numKernStructFieldNames, kernStructFieldNames, &kernStruct); PsychSetStructArrayStringElement("ostype", 0, unameresult.sysname, kernStruct); PsychSetStructArrayStringElement("osrelease", 0, unameresult.release, kernStruct); PsychSetStructArrayDoubleElement("osrevision", 0, 0, kernStruct); sprintf(tmpString, "%s Kernel Version %s: %s", unameresult.sysname, unameresult.release, unameresult.version); PsychSetStructArrayStringElement("version", 0, tmpString, kernStruct); PsychSetStructArrayStringElement("hostname", 0, unameresult.nodename, kernStruct); PsychSetStructArrayStructElement("kern",0, kernStruct, majorStruct); PsychSetStructArrayStringElement("localHostName", 0, unameresult.nodename, majorStruct); PsychSetStructArrayStringElement("machineName", 0, unameresult.nodename, majorStruct); // Fill the hw struct and implant it within the major struct: PsychAllocOutStructArray(-1, FALSE, numHwStructDimensions, numHwStructFieldNames, hwStructFieldNames, &hwStruct); PsychSetStructArrayStringElement("machine", 0, unameresult.machine, hwStruct); PsychSetStructArrayStringElement("model", 0, "", hwStruct); PsychSetStructArrayDoubleElement("ncpu", 0, (double) sysconf(_SC_NPROCESSORS_ONLN), hwStruct); PsychSetStructArrayDoubleElement("physmem", 0, ((double) sysconf(_SC_PHYS_PAGES)) * ((double) sysconf(_SC_PAGESIZE)), hwStruct); PsychSetStructArrayDoubleElement("usermem", 0, ((double) sysconf(_SC_AVPHYS_PAGES)) * ((double) sysconf(_SC_PAGESIZE)), hwStruct); PsychSetStructArrayDoubleElement("busfreq", 0, 0, hwStruct); PsychSetStructArrayDoubleElement("cpufreq", 0, 0, hwStruct); PsychSetStructArrayStructElement("hw",0, hwStruct, majorStruct); return(PsychError_none); }
PsychError SCREENComputer(void) { const char *majorStructFieldNames[]={"macintosh", "windows", "osx" ,"linux", "kern", "hw", "processUserLongName", "processUserShortName", "consoleUserName", "machineName", "localHostName", "location", "MACAddress", "system", "gstreamer", "supported" }; const char *kernStructFieldNames[]={"ostype", "osrelease", "osrevision", "version","hostname"}; const char *hwStructFieldNames[]={"machine", "model", "ncpu", "physmem", "usermem", "busfreq", "cpufreq"}; int numMajorStructDimensions=-1, numKernStructDimensions=-1, numHwStructDimensions=-1; int numMajorStructFieldNames=16, numKernStructFieldNames=5, numHwStructFieldNames=7; PsychGenericScriptType *kernStruct, *hwStruct, *majorStruct; //char tempStr[CTL_MAXNAME]; //this seems like a bug in Darwin, CTL_MAXNAME is shorter than the longest name. char tempStr[256], *ethernetMACStr; size_t tempIntSize, tempStrSize, tempULongIntSize; int mib[2]; int tempInt; psych_uint64 tempULongInt; char *tempStrPtr; CFStringRef tempCFStringRef; psych_bool stringSuccess; int stringLengthChars, ethernetMACStrSizeBytes; long gestaltResult; OSErr gestaltError; int i,strIndex, bcdDigit, lengthSystemVersionString; int osMajor, osMinor, osBugfix; char systemVersionStr[256]; //all subfunctions should have these two lines PsychPushHelp(useString, synopsisString, seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; PsychErrorExit(PsychCapNumOutputArgs(1)); PsychErrorExit(PsychCapNumInputArgs(0)); //fill the major struct PsychAllocOutStructArray(1, FALSE, numMajorStructDimensions, numMajorStructFieldNames, majorStructFieldNames, &majorStruct); PsychSetStructArrayDoubleElement("macintosh", 0, 0, majorStruct); PsychSetStructArrayDoubleElement("windows", 0, 0, majorStruct); PsychSetStructArrayDoubleElement("linux", 0, 0, majorStruct); PsychSetStructArrayDoubleElement("osx", 0, 1, majorStruct); // Official support status: PsychSetStructArrayStringElement("supported", 0, (char*) PsychSupportStatus(), majorStruct); // GStreamer availability and rough version: #if defined(PTB_USE_GSTREAMER) #if GST_CHECK_VERSION(1,0,0) PsychSetStructArrayDoubleElement("gstreamer", 0, 1 * 10000 + 0 * 100 + 0, majorStruct); #else PsychSetStructArrayDoubleElement("gstreamer", 0, 0 * 10000 + 10 * 100 + 0, majorStruct); #endif #else PsychSetStructArrayDoubleElement("gstreamer", 0, 0, majorStruct); #endif //fill the kern struct and implant it within the major struct PsychAllocOutStructArray(-1, FALSE, numKernStructDimensions, numKernStructFieldNames, kernStructFieldNames, &kernStruct); mib[0]=CTL_KERN; mib[1]=KERN_OSTYPE; tempStrSize=sizeof(tempStr); ReportSysctlError(sysctl(mib, 2, tempStr, &tempStrSize, NULL, 0)); PsychSetStructArrayStringElement("ostype", 0, tempStr, kernStruct); mib[1]=KERN_OSRELEASE; tempStrSize=sizeof(tempStr); ReportSysctlError(sysctl(mib, 2, tempStr, &tempStrSize, NULL, 0)); PsychSetStructArrayStringElement("osrelease", 0, tempStr, kernStruct); mib[1]=KERN_OSREV; tempIntSize=sizeof(tempInt); ReportSysctlError(sysctl(mib, 2, &tempInt, &tempIntSize, NULL, 0)); PsychSetStructArrayDoubleElement("osrevision", 0, (double)tempInt, kernStruct); mib[1]=KERN_VERSION; tempStrSize=sizeof(tempStr); ReportSysctlError(sysctl(mib, 2, tempStr, &tempStrSize, NULL, 0)); PsychSetStructArrayStringElement("version", 0, tempStr, kernStruct); mib[1]=KERN_HOSTNAME; tempStrSize=sizeof(tempStr); ReportSysctlError(sysctl(mib, 2, tempStr, &tempStrSize, NULL, 0)); PsychSetStructArrayStringElement("hostname", 0, tempStr, kernStruct); PsychSetStructArrayStructElement("kern",0, kernStruct, majorStruct); //fill the hw struct and implant it within the major struct PsychAllocOutStructArray(-1, FALSE, numHwStructDimensions, numHwStructFieldNames, hwStructFieldNames, &hwStruct); mib[0]=CTL_HW; mib[1]=HW_MACHINE; tempStrSize=sizeof(tempStr); ReportSysctlError(sysctl(mib, 2, tempStr, &tempStrSize, NULL, 0)); PsychSetStructArrayStringElement("machine", 0, tempStr, hwStruct); mib[1]=HW_MODEL; tempStrSize=sizeof(tempStr); ReportSysctlError(sysctl(mib, 2, tempStr, &tempStrSize, NULL, 0)); PsychSetStructArrayStringElement("model", 0, tempStr, hwStruct); mib[1]=HW_NCPU; tempIntSize=sizeof(tempInt); ReportSysctlError(sysctl(mib, 2, &tempInt, &tempIntSize, NULL, 0)); PsychSetStructArrayDoubleElement("ncpu", 0, (double)tempInt, hwStruct); mib[1]=HW_MEMSIZE; tempULongIntSize=sizeof(tempULongInt); tempULongInt = 0; ReportSysctlError(sysctl(mib, 2, &tempULongInt, &tempULongIntSize, NULL, 0)); PsychSetStructArrayDoubleElement("physmem", 0, (double)tempULongInt, hwStruct); mib[1]=HW_USERMEM; tempULongIntSize=sizeof(tempULongInt); tempULongInt = 0; ReportSysctlError(sysctlbyname("hw.usermem", &tempULongInt, &tempULongIntSize, NULL, 0)); PsychSetStructArrayDoubleElement("usermem", 0, (double)tempULongInt, hwStruct); mib[1]=HW_BUS_FREQ; tempULongIntSize=sizeof(tempULongInt); tempULongInt = 0; ReportSysctlError(sysctlbyname("hw.busfrequency", &tempULongInt, &tempULongIntSize, NULL, 0)); PsychSetStructArrayDoubleElement("busfreq", 0, (double)tempULongInt, hwStruct); mib[1]=HW_CPU_FREQ; tempULongIntSize=sizeof(tempULongInt); tempULongInt = 0; ReportSysctlError(sysctlbyname("hw.cpufrequency", &tempULongInt, &tempULongIntSize, NULL, 0)); PsychSetStructArrayDoubleElement("cpufreq", 0, (double)tempULongInt, hwStruct); PsychSetStructArrayStructElement("hw",0, hwStruct, majorStruct); //fill in the process user, console user and machine name in the root struct. tempCFStringRef = SCDynamicStoreCopyComputerName(NULL, NULL); if (tempCFStringRef) { stringLengthChars=(int) CFStringGetMaximumSizeForEncoding(CFStringGetLength(tempCFStringRef), kCFStringEncodingASCII); tempStrPtr=malloc(sizeof(char) * (stringLengthChars+1)); stringSuccess= CFStringGetCString(tempCFStringRef, tempStrPtr, stringLengthChars+1, kCFStringEncodingASCII); if(stringSuccess) { PsychSetStructArrayStringElement("machineName", 0, tempStrPtr, majorStruct); } else { PsychSetStructArrayStringElement("machineName", 0, "UNKNOWN! QUERY FAILED DUE TO EMPTY OR PROBLEMATIC NAME.", majorStruct); } free(tempStrPtr); CFRelease(tempCFStringRef); } else { PsychSetStructArrayStringElement("machineName", 0, "UNKNOWN! QUERY FAILED DUE TO EMPTY OR PROBLEMATIC NAME.", majorStruct); } struct passwd* thisUser = getpwuid(getuid()); if (thisUser) { PsychSetStructArrayStringElement("processUserShortName", 0, thisUser->pw_name, majorStruct); } else { PsychSetStructArrayStringElement("processUserShortName", 0, "UNKNOWN! QUERY FAILED DUE TO EMPTY OR PROBLEMATIC NAME.", majorStruct); } PsychSetStructArrayStringElement("processUserLongName", 0, PsychCocoaGetFullUsername(), majorStruct); tempCFStringRef= SCDynamicStoreCopyConsoleUser(NULL, NULL, NULL); if (tempCFStringRef) { stringLengthChars=(int) CFStringGetMaximumSizeForEncoding(CFStringGetLength(tempCFStringRef), kCFStringEncodingASCII); tempStrPtr=malloc(sizeof(char) * (stringLengthChars+1)); stringSuccess= CFStringGetCString(tempCFStringRef, tempStrPtr, stringLengthChars+1, kCFStringEncodingASCII); if(stringSuccess) { PsychSetStructArrayStringElement("consoleUserName", 0, tempStrPtr, majorStruct); } else { PsychSetStructArrayStringElement("consoleUserName", 0, "UNKNOWN! QUERY FAILED DUE TO EMPTY OR PROBLEMATIC NAME.", majorStruct); } free(tempStrPtr); CFRelease(tempCFStringRef); } else { PsychSetStructArrayStringElement("consoleUserName", 0, "UNKNOWN! QUERY FAILED DUE TO EMPTY OR PROBLEMATIC NAME.", majorStruct); } tempCFStringRef= SCDynamicStoreCopyLocalHostName(NULL); if (tempCFStringRef) { stringLengthChars=(int) CFStringGetMaximumSizeForEncoding(CFStringGetLength(tempCFStringRef), kCFStringEncodingASCII); tempStrPtr=malloc(sizeof(char) * (stringLengthChars+1)); stringSuccess= CFStringGetCString(tempCFStringRef, tempStrPtr, stringLengthChars+1, kCFStringEncodingASCII); if(stringSuccess) { PsychSetStructArrayStringElement("localHostName", 0, tempStrPtr, majorStruct); } else { PsychSetStructArrayStringElement("localHostName", 0, "UNKNOWN! QUERY FAILED DUE TO EMPTY OR PROBLEMATIC NAME.", majorStruct); } free(tempStrPtr); CFRelease(tempCFStringRef); } else { PsychSetStructArrayStringElement("localHostName", 0, "UNKNOWN! QUERY FAILED DUE TO EMPTY OR PROBLEMATIC NAME.", majorStruct); } tempCFStringRef= SCDynamicStoreCopyLocation(NULL); if (tempCFStringRef) { stringLengthChars=(int) CFStringGetMaximumSizeForEncoding(CFStringGetLength(tempCFStringRef), kCFStringEncodingASCII); tempStrPtr=malloc(sizeof(char) * (stringLengthChars+1)); stringSuccess= CFStringGetCString(tempCFStringRef, tempStrPtr, stringLengthChars+1, kCFStringEncodingASCII); if(stringSuccess) { PsychSetStructArrayStringElement("location", 0, tempStrPtr, majorStruct); } else { PsychSetStructArrayStringElement("location", 0, "UNKNOWN! QUERY FAILED DUE TO EMPTY OR PROBLEMATIC NAME.", majorStruct); } free(tempStrPtr); CFRelease(tempCFStringRef); } else { PsychSetStructArrayStringElement("location", 0, "UNKNOWN! QUERY FAILED DUE TO EMPTY OR PROBLEMATIC NAME.", majorStruct); } //Add the ethernet MAC address of the primary ethernet interface to the stuct. This can serve as a unique identifier for the computer. ethernetMACStrSizeBytes=GetPrimaryEthernetAddressStringLengthBytes(TRUE)+1; ethernetMACStr=(char*) malloc(sizeof(char) * ethernetMACStrSizeBytes); GetPrimaryEthernetAddressString(ethernetMACStr, TRUE, TRUE); PsychSetStructArrayStringElement("MACAddress", 0, ethernetMACStr, majorStruct); free(ethernetMACStr); //Add the system version string: PsychCocoaGetOSXVersion(&osMajor, &osMinor, &osBugfix); sprintf(systemVersionStr, "Mac OS %i.%i.%i", osMajor, osMinor, osBugfix); //embed it in the return struct PsychSetStructArrayStringElement("system", 0, systemVersionStr, majorStruct); return(PsychError_none); }
PsychError SCREENGetMouseHelper(void) { const char *valuatorInfo[]={"label", "min", "max", "resolution", "mode", "sourceID"}; int numValuatorStructFieldNames = 6; int numIValuators = 0; PsychGenericScriptType *valuatorStruct = NULL; #if PSYCH_SYSTEM == PSYCH_OSX Point mouseXY; UInt32 buttonState; double *buttonArray; int numButtons, i; psych_bool doButtonArray; PsychWindowRecordType *windowRecord; //all subfunctions should have these two lines. PsychPushHelp(useString, synopsisString, seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; //cap the numbers of inputs and outputs PsychErrorExit(PsychCapNumInputArgs(3)); //The maximum number of inputs PsychErrorExit(PsychCapNumOutputArgs(6)); //The maximum number of outputs //Buttons. // The only way I know to detect the number number of mouse buttons is directly via HID. The device reports //that information but OS X seems to ignore it above the level of the HID driver, that is, no OS X API above the HID driver //exposes it. So GetMouse.m function calls PsychHID detect the number of buttons and then passes that value to GetMouseHelper //which returns that number of button values in a vector. PsychCopyInIntegerArg(1, kPsychArgRequired, &numButtons); if(numButtons > 32) PsychErrorExitMsg(PsychErorr_argumentValueOutOfRange, "numButtons must not exceed 32"); // Special codes -10 to -15? --> Console keyboard queries: if(numButtons <= -10 && numButtons >= -15) { ConsoleInputHelper((int) numButtons); return(PsychError_none); } if(numButtons < 1) PsychErrorExitMsg(PsychErorr_argumentValueOutOfRange, "numButtons must exceed 1"); doButtonArray=PsychAllocOutDoubleMatArg(3, kPsychArgOptional, (int)1, (int)numButtons, (int)1, &buttonArray); if(doButtonArray){ buttonState=GetCurrentButtonState(); for(i=0;i<numButtons;i++) buttonArray[i]=(double)(buttonState & (1<<i)); } // Get cursor position: #ifndef __LP64__ // 32-Bit Carbon version: GetGlobalMouse(&mouseXY); PsychCopyOutDoubleArg(1, kPsychArgOptional, (double)mouseXY.h); PsychCopyOutDoubleArg(2, kPsychArgOptional, (double)mouseXY.v); #else // 64-Bit HIToolbox version (OSX 10.5 and later): HIPoint outPoint; HIGetMousePosition(kHICoordSpaceScreenPixel, NULL, &outPoint); PsychCopyOutDoubleArg(1, kPsychArgOptional, (double) outPoint.x); PsychCopyOutDoubleArg(2, kPsychArgOptional, (double) outPoint.y); #endif // Return optional keyboard input focus status: if (numButtons > 0) { // Window provided? // We only have the function GetUserFocusWindow on 32-Bit Carbon. // We have a drop-in replacement in OSX/PsychCocoaGlue.c for 64-Bit Cocoa. if (PsychIsWindowIndexArg(2)) { // Yes: Check if it has focus. PsychAllocInWindowRecordArg(2, TRUE, &windowRecord); if (!PsychIsOnscreenWindow(windowRecord)) { PsychErrorExitMsg(PsychError_user, "Provided window handle isn't an onscreen window, as required."); } PsychCopyOutDoubleArg(4, kPsychArgOptional, (double) (GetUserFocusWindow() == windowRecord->targetSpecific.windowHandle) ? 1 : 0); } else { // No. Just always return "has focus": PsychCopyOutDoubleArg(4, kPsychArgOptional, (double) 1); } } // Return optional valuator values: Unimplemented on OS/X. Just return an empty matrix. // The buttonArray is just a dummy assignment without any meaning. PsychCopyOutDoubleMatArg(5, kPsychArgOptional, (int) 1, (int) 0, (int) 1, buttonArray); PsychCopyOutDoubleMatArg(6, kPsychArgOptional, (int) 1, (int) 0, (int) 1, buttonArray); #endif #if PSYCH_SYSTEM == PSYCH_WINDOWS static unsigned char disabledKeys[256]; static unsigned char firsttime = 1; int keysdown, i, priorityLevel; unsigned char keyState[256]; double* buttonArray; double numButtons, timestamp; PsychNativeBooleanType* buttonStates; POINT point; HANDLE currentProcess; DWORD oldPriority = NORMAL_PRIORITY_CLASS; const DWORD realtime_class = REALTIME_PRIORITY_CLASS; PsychWindowRecordType *windowRecord; PsychPushHelp(useString, synopsisString, seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; // Retrieve optional number of mouse buttons: numButtons = 0; PsychCopyInDoubleArg(1, FALSE, &numButtons); // Are we operating in 'GetMouseHelper' mode? numButtons>=0 indicates this. if (numButtons>=0) { // GetMouse-Mode: Return mouse button states and mouse cursor position: PsychAllocOutDoubleMatArg(3, kPsychArgOptional, (int)1, (int)3, (int)1, &buttonArray); // Query and return mouse button state: PsychGetMouseButtonState(buttonArray); // Query and return cursor position in global coordinates: GetCursorPos(&point); PsychCopyOutDoubleArg(1, kPsychArgOptional, (double) point.x); PsychCopyOutDoubleArg(2, kPsychArgOptional, (double) point.y); // Window provided? if (PsychIsWindowIndexArg(2)) { // Yes: Check if it has focus. PsychAllocInWindowRecordArg(2, TRUE, &windowRecord); if (!PsychIsOnscreenWindow(windowRecord)) { PsychErrorExitMsg(PsychError_user, "Provided window handle isn't an onscreen window, as required."); } PsychCopyOutDoubleArg(4, kPsychArgOptional, (double) (GetForegroundWindow() == windowRecord->targetSpecific.windowHandle) ? 1 : 0); } else { // No. Just always return "has focus": PsychCopyOutDoubleArg(4, kPsychArgOptional, (double) 1); } // Return optional valuator values: Unimplemented on Windows. Just return an empty matrix. // The ×tamp is just a dummy assignment without any meaning. PsychCopyOutDoubleMatArg(5, kPsychArgOptional, (int) 1, (int) 0, (int) 1, ×tamp); PsychCopyOutDoubleMatArg(6, kPsychArgOptional, (int) 1, (int) 0, (int) 1, buttonArray); } else { // 'KeyboardHelper' mode: We implement either KbCheck() or KbWait() via X11. // This is a hack to provide keyboard queries until a PsychHID() implementation // for Microsoft Windows is available... // Special codes -10 to -15? --> Console keyboard queries: if(numButtons <= -10 && numButtons >= -15) { ConsoleInputHelper((int) numButtons); return(PsychError_none); } if (firsttime) { // First time init: firsttime = 0; memset(keyState, 0, sizeof(keyState)); memset(disabledKeys, 0, sizeof(disabledKeys)); // These keycodes are always disabled: 0, 255: disabledKeys[0]=1; disabledKeys[255]=1; // Mouse buttone (left, right, middle) are also disabled by default: disabledKeys[1]=1; disabledKeys[2]=1; disabledKeys[4]=1; } if (numButtons==-1 || numButtons==-2) { // KbCheck()/KbWait() mode do { // Reset overall key state to "none pressed": keysdown=0; // Request current time of query: PsychGetAdjustedPrecisionTimerSeconds(×tamp); // Query state of all keys: for(i=1;i<255;i++){ keyState[i] = (GetAsyncKeyState(i) & -32768) ? 1 : 0; } // Disable all keys that are registered in disabledKeys. Check if // any non-disabled key is down. for (i=0; i<256; i++) { if (disabledKeys[i]>0) keyState[i] = 0; keysdown+=(unsigned int) keyState[i]; } // We repeat until any key pressed if in KbWait() mode, otherwise we // exit the loop after first iteration in KbCheck mode. if ((numButtons==-1) || ((numButtons==-2) && (keysdown>0))) break; // Sleep for a millisecond before next KbWait loop iteration: PsychWaitIntervalSeconds(0.001); } while(1); if (numButtons==-2) { // KbWait mode: Copy out time value. PsychCopyOutDoubleArg(1, kPsychArgOptional, timestamp); } else { // KbCheck mode: // Copy out overall keystate: PsychCopyOutDoubleArg(1, kPsychArgOptional, (keysdown>0) ? 1 : 0); // Copy out timestamp: PsychCopyOutDoubleArg(2, kPsychArgOptional, timestamp); // Copy out keyboard state: PsychAllocOutBooleanMatArg(3, kPsychArgOptional, 1, 256, 1, &buttonStates); // Build 256 elements return vector: for(i=0; i<255; i++) { buttonStates[i] = (PsychNativeBooleanType)((keyState[i+1]) ? 1 : 0); } // Special case: Null out last element: buttonStates[255] = (PsychNativeBooleanType) 0; } } if (numButtons==-3) { // Priority() - helper mode: The 2nd argument is the priority level: // Determine our processID: currentProcess = GetCurrentProcess(); // Get current scheduling policy: oldPriority = GetPriorityClass(currentProcess); // Map to PTB's scheme: switch(oldPriority) { case NORMAL_PRIORITY_CLASS: priorityLevel = 0; break; case HIGH_PRIORITY_CLASS: priorityLevel = 1; break; case REALTIME_PRIORITY_CLASS: priorityLevel = 2; break; default: priorityLevel = 0; } // Copy it out as optional return argument: PsychCopyOutDoubleArg(1, kPsychArgOptional, (double) priorityLevel); // Query if a new level should be set: priorityLevel = -1; PsychCopyInIntegerArg(2, kPsychArgOptional, &priorityLevel); // Priority level provided? if (priorityLevel > -1) { // Map to new scheduling class: if (priorityLevel > 2) PsychErrorExitMsg(PsychErorr_argumentValueOutOfRange, "Invalid Priority level: Requested Priority() level must not exceed 2."); switch(priorityLevel) { case 0: // Standard scheduling: SetPriorityClass(currentProcess, NORMAL_PRIORITY_CLASS); // Disable any MMCSS scheduling for us: PsychSetThreadPriority((psych_thread*) 0x1, 0, 0); break; case 1: // High priority scheduling: SetPriorityClass(currentProcess, HIGH_PRIORITY_CLASS); // Additionally try to schedule us MMCSS: This will lift us roughly into the // same scheduling range as REALTIME_PRIORITY_CLASS, even if we are non-admin users // on Vista and Windows-7 and later, however with a scheduler safety net applied. PsychSetThreadPriority((psych_thread*) 0x1, 10, 0); break; case 2: // Realtime scheduling: // This can fail if Matlab is not running under a user account with proper permissions: if ((0 == SetPriorityClass(currentProcess, REALTIME_PRIORITY_CLASS)) || (REALTIME_PRIORITY_CLASS != GetPriorityClass(currentProcess))) { // Failed to get RT-Scheduling. Let's try at least high priority scheduling: SetPriorityClass(currentProcess, HIGH_PRIORITY_CLASS); // Additionally try to schedule us MMCSS: This will lift us roughly into the // same scheduling range as REALTIME_PRIORITY_CLASS, even if we are non-admin users // on Vista and Windows-7 and later, however with a scheduler safety net applied. PsychSetThreadPriority((psych_thread*) 0x1, 10, 0); } break; } } // End of Priority() helper for Win32. } } #endif #if PSYCH_SYSTEM == PSYCH_LINUX double myvaluators[100]; int numvaluators; unsigned char keys_return[32]; char* keystring; PsychGenericScriptType *kbNames; CGDirectDisplayID dpy; Window rootwin, childwin, mywin; int i, j, mx, my, dx, dy; double mxd, myd, dxd, dyd; unsigned int mask_return; double timestamp; int numButtons; double* buttonArray; PsychNativeBooleanType* buttonStates; int keysdown; XEvent event_return; XKeyPressedEvent keypressevent; int screenNumber; int priorityLevel; struct sched_param schedulingparam; PsychWindowRecordType *windowRecord; int mouseIndex; XIButtonState buttons_return; XIModifierState modifiers_return; XIGroupState group_return; PsychPushHelp(useString, synopsisString, seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; PsychCopyInIntegerArg(1, kPsychArgRequired, &numButtons); // Retrieve optional screenNumber argument: if (numButtons!=-5) { screenNumber = 0; if (PsychIsScreenNumberArg(2)) { PsychCopyInScreenNumberArg(2, FALSE, &screenNumber); } // Map screenNumber to X11 display handle and screenid: PsychGetCGDisplayIDFromScreenNumber(&dpy, screenNumber); if (PsychIsWindowIndexArg(2)) { PsychAllocInWindowRecordArg(2, TRUE, &windowRecord); if (!PsychIsOnscreenWindow(windowRecord)) { PsychErrorExitMsg(PsychError_user, "Provided window handle isn't an onscreen window, as required."); } screenNumber = windowRecord->screenNumber; mywin = windowRecord->targetSpecific.xwindowHandle; // Map screenNumber to X11 display handle and screenid: PsychGetCGDisplayIDFromScreenNumber(&dpy, screenNumber); } else { mywin = RootWindow(dpy, PsychGetXScreenIdForScreen(screenNumber)); } } // Default to "old school" mouse query - System default mouse via X core protocol: mouseIndex = -1; PsychCopyInIntegerArg(3, FALSE, &mouseIndex); // Are we operating in 'GetMouseHelper' mode? numButtons>=0 indicates this. if (numButtons>=0) { // Mouse pointer query mode: numvaluators = 0; if (mouseIndex >= 0) { // XInput-2 query for handling of multiple mouse pointers: // Query input device list for screen: int nDevices; XIDeviceInfo* indevs = PsychGetInputDevicesForScreen(screenNumber, &nDevices); // Sanity check: if (NULL == indevs) PsychErrorExitMsg(PsychError_user, "Sorry, your system does not support individual mouse pointer queries."); if (mouseIndex >= nDevices) PsychErrorExitMsg(PsychError_user, "Invalid 'mouseIndex' provided. No such device."); if ((indevs[mouseIndex].use != XIMasterPointer) && (indevs[mouseIndex].use != XISlavePointer) && (indevs[mouseIndex].use != XIFloatingSlave)) { PsychErrorExitMsg(PsychError_user, "Invalid 'mouseIndex' provided. Not a pointer device."); } // We requery the device info struct to retrieve updated live device state: // Crucial for slave pointers to get any state at all, but also needed on // master pointers to get the state of additional valuators, e.g., pen pressure, // touch area, tilt etc. for digitizer tablets, touch pads etc. For master pointers, // the primary 2 axis for 2D (x,y) position and the button/modifier state will be // queried via a dedicated XIQueryPointer() call, so that info gets overriden. indevs = XIQueryDevice(dpy, indevs[mouseIndex].deviceid, &numButtons); modifiers_return.effective = 0; // Query real number of mouse buttons and the raw button and axis state // stored inside the device itself. This is done mostly because slave pointer // devices don't support XIQueryPointer() so we get their relevant info from the // XIDeviceInfo struct itself: numButtons = 0; numvaluators = 0; memset(myvaluators, 0, sizeof(myvaluators)); if (PsychIsArgPresent(PsychArgOut, 6)) { // Usercode wants valuator info structs: for (i = 0; i < indevs->num_classes; i++) if (indevs->classes[i]->type == XIValuatorClass) numIValuators++; PsychAllocOutStructArray(6, TRUE, numIValuators, numValuatorStructFieldNames, valuatorInfo, &valuatorStruct); } for (i = 0; i < indevs->num_classes; i++) { // printf("Class %i: Type %i\n", i, (int) indevs->classes[i]->type); if (indevs->classes[i]->type == XIButtonClass) { // Number of buttons: For all pointers. numButtons = ((XIButtonClassInfo*) indevs->classes[i])->num_buttons; // Button state for slave pointers. Will get overriden for master pointers: buttons_return.mask = ((XIButtonClassInfo*) indevs->classes[i])->state.mask; buttons_return.mask_len = ((XIButtonClassInfo*) indevs->classes[i])->state.mask_len; } // Axis state for slave pointers. First two axis (x,y) will get overriden for master pointers: if (indevs->classes[i]->type == XIValuatorClass) { XIValuatorClassInfo* axis = (XIValuatorClassInfo*) indevs->classes[i]; if (axis->number == 0) mxd = axis->value; // x-Axis. if (axis->number == 1) myd = axis->value; // y-Axis. // Additional axis, e.g., digitizer tablet, touchpads etc.: if (axis->number >= 0 && axis->number < 100) { myvaluators[axis->number] = axis->value; numvaluators = (numvaluators >= axis->number + 1) ? numvaluators : axis->number + 1; } // Assign valuator info struct, if requested: if (valuatorStruct) { if (axis->label != None) { char* atomlabel = XGetAtomName(dpy, axis->label); PsychSetStructArrayStringElement("label", axis->number, atomlabel, valuatorStruct); XFree(atomlabel); } else { PsychSetStructArrayStringElement("label", axis->number, "None", valuatorStruct); } PsychSetStructArrayDoubleElement("min", axis->number, (double) axis->min, valuatorStruct); PsychSetStructArrayDoubleElement("max", axis->number, (double) axis->max, valuatorStruct); PsychSetStructArrayDoubleElement("resolution", axis->number, (double) axis->resolution, valuatorStruct); PsychSetStructArrayDoubleElement("mode", axis->number, (double) axis->mode, valuatorStruct); PsychSetStructArrayDoubleElement("sourceID", axis->number, (double) axis->sourceid, valuatorStruct); } // printf("AXIS %i, LABEL = %s, MIN = %f, MAX = %f, VAL = %f\n", axis->number, (char*) "NONE", (float) axis->min, (float) axis->max, (float) axis->value); } } // Add 32 buttons for modifier key state vector: numButtons += 32; // A real master pointer: Use official query for mouse devices. if (indevs->use == XIMasterPointer) { // Query pointer location and state: XIQueryPointer(dpy, indevs->deviceid, RootWindow(dpy, PsychGetXScreenIdForScreen(screenNumber)), &rootwin, &childwin, &mxd, &myd, &dxd, &dyd, &buttons_return, &modifiers_return, &group_return); } // Copy out mouse x and y position: PsychCopyOutDoubleArg(1, kPsychArgOptional, mxd); PsychCopyOutDoubleArg(2, kPsychArgOptional, myd); // Copy out mouse button state: PsychAllocOutDoubleMatArg(3, kPsychArgOptional, (int)1, (int) numButtons, (int)1, &buttonArray); memset(buttonArray, 0, sizeof(double) * numButtons); if (numButtons > 0) { // Mouse buttons: const int buttonOffset = 1; // Buttons start at bit 1, not 0 for some strange reason? At least so on Ubuntu 10.10 and 11.10 with 2 mice and 1 joystick? for (i = buttonOffset; (i < numButtons - 32) && ((i / 8 ) < buttons_return.mask_len); i++) { buttonArray[i - buttonOffset] = (double) ((buttons_return.mask[i / 8] & (1 << (i % 8))) ? 1 : 0); } // Free mask if retrieved via XIQueryPointer(): if (indevs->use == XIMasterPointer) free(buttons_return.mask); // Append modifier key state from associated master keyboard. Last 32 entries: for (i = 0; i < 32; i++) { buttonArray[numButtons - 32 + i] = (double) ((modifiers_return.effective & (1 << i)) ? 1 : 0); } } // Release live state info structure: XIFreeDeviceInfo(indevs); } else { // Old school core protocol query of virtual core pointer: XQueryPointer(dpy, RootWindow(dpy, PsychGetXScreenIdForScreen(screenNumber)), &rootwin, &childwin, &mx, &my, &dx, &dy, &mask_return); // Copy out mouse x and y position: PsychCopyOutDoubleArg(1, kPsychArgOptional, (double) mx); PsychCopyOutDoubleArg(2, kPsychArgOptional, (double) my); // Copy out mouse button state: PsychAllocOutDoubleMatArg(3, kPsychArgOptional, (int)1, (int)numButtons, (int)1, &buttonArray); // Bits 8, 9 and 10 of mask_return seem to correspond to mouse buttons // 1, 2 and 3 of a mouse for some weird reason. Bits 0-7 describe keyboard modifier keys // like Alt, Ctrl, Shift, ScrollLock, NumLock, CapsLock... // We remap here, so the first three returned entries correspond to the mouse buttons and // the rest is attached behind, if requested... // Mouse buttons: Left, Middle, Right == 0, 1, 2, aka 1,2,3 in Matlab space... for (i=0; i<numButtons && i<3; i++) { buttonArray[i] = (mask_return & (1<<(i+8))) ? 1 : 0; } // Modifier keys 0 to 7 appended: for (i=3; i<numButtons && i<3+8; i++) { buttonArray[i] = (mask_return & (1<<(i-3))) ? 1 : 0; } // Everything else appended: for (i=11; i<numButtons; i++) { buttonArray[i] = (mask_return & (1<<i)) ? 1 : 0; } } // Return optional 4th argument: Focus state. Returns 1 if our window has // keyboard input focus, zero otherwise: XGetInputFocus(dpy, &rootwin, &i); PsychCopyOutDoubleArg(4, kPsychArgOptional, (double) (rootwin == mywin) ? 1 : 0); // Return optional valuator values: PsychCopyOutDoubleMatArg(5, kPsychArgOptional, (int) 1, (int) numvaluators, (int) 1, &myvaluators[0]); } else { // 'KeyboardHelper' mode: We implement either KbCheck() or KbWait() via X11. // This is a hack to provide keyboard queries until a PsychHID() implementation // for Linux is available... // Special codes -10 to -15? --> Console keyboard queries: if(numButtons <= -10 && numButtons >= -15) { ConsoleInputHelper((int) numButtons); return(PsychError_none); } if (numButtons==-1 || numButtons==-2) { // KbCheck()/KbWait() mode: // Switch X-Server into synchronous mode: We need this to get // a higher timing precision. XSynchronize(dpy, TRUE); do { // Reset overall key state to "none pressed": keysdown=0; // Request current keyboard state from X-Server: XQueryKeymap(dpy, keys_return); // Request current time of query: PsychGetAdjustedPrecisionTimerSeconds(×tamp); // Any key down? for (i=0; i<32; i++) keysdown+=(unsigned int) keys_return[i]; // We repeat until any key pressed if in KbWait() mode, otherwise we // exit the loop after first iteration in KbCheck mode. if ((numButtons==-1) || ((numButtons==-2) && (keysdown>0))) break; // Sleep for a few milliseconds before next KbWait loop iteration: PsychWaitIntervalSeconds(0.01); } while(1); if (numButtons==-2) { // Copy out time: PsychCopyOutDoubleArg(1, kPsychArgOptional, timestamp); } else { // KbCheck mode: // Copy out overall keystate: PsychCopyOutDoubleArg(1, kPsychArgOptional, (keysdown>0) ? 1 : 0); // copy out timestamp: PsychCopyOutDoubleArg(2, kPsychArgOptional, timestamp); // Copy keyboard state: PsychAllocOutBooleanMatArg(3, kPsychArgOptional, 1, 256, 1, &buttonStates); // Map 32 times 8 bitvector to 256 element return vector: for(i=0; i<32; i++) { for(j=0; j<8; j++) { buttonStates[i*8 + j] = (PsychNativeBooleanType)(keys_return[i] & (1<<j)) ? 1 : 0; } } } } else if (numButtons == -3) { // numButtons == -3 --> KbName mapping mode: // Return the full keyboard keycode to ASCII character code mapping table... PsychAllocOutCellVector(1, kPsychArgOptional, 256, &kbNames); for(i=0; i<256; i++) { // Map keyboard scan code to KeySym: keystring = XKeysymToString(XKeycodeToKeysym(dpy, i, 0)); if (keystring) { // Character found: Return its ASCII name string: PsychSetCellVectorStringElement(i, keystring, kbNames); } else { // No character for this keycode: PsychSetCellVectorStringElement(i, "", kbNames); } } } else if (numButtons == -4) { // GetChar() emulation. /* do { */ /* // Fetch next keypress event from queue, block if none is available... */ /* keystring = NULL; */ /* XNextEvent(dpy, &event_return); */ /* // Check for valid keypress event and extract character: */ /* if (event_return.type == KeyPress) { */ /* keypressevent = (XKeyPressedEvent) event_return; */ /* keystring = NULL; */ /* keystring = XKeysymToString(XKeycodeToKeysym(dpy, keypressevent.keycode, 0)); */ /* } */ /* // Repeat until a valid char is returned. */ /* } while (keystring == NULL); */ /* // Copy out character: */ /* PsychCopyOutCharArg(1, kPsychArgOptional, (char) keystring); */ /* // Copy out time: */ /* PsychCopyOutDoubleArg(2, kPsychArgOptional, (double) keypressevent.time); */ } else if (numButtons==-5) { // Priority() - helper mode: The 2nd argument is the priority level: // Query scheduling policy and priority: pthread_getschedparam(pthread_self(), &priorityLevel, &schedulingparam); // If scheduling mode is a realtime mode (RoundRobin realtime RR, or FIFO realtime), // then assign RT priority level (range 1-99) as current priorityLevel, otherwise // assign non realtime priority level zero: priorityLevel = (priorityLevel == SCHED_RR || priorityLevel == SCHED_FIFO) ? schedulingparam.sched_priority : 0; // Copy it out as optional return argument: PsychCopyOutDoubleArg(1, kPsychArgOptional, (double) priorityLevel); // Query if a new level should be set: priorityLevel = -1; PsychCopyInIntegerArg(2, kPsychArgOptional, &priorityLevel); errno=0; // Priority level provided? if (priorityLevel > -1) { // Map to new scheduling class: if (priorityLevel > 99 || priorityLevel < 0) PsychErrorExitMsg(PsychErorr_argumentValueOutOfRange, "Invalid Priority level: Requested Priority() level must be between zero and 99!"); if (priorityLevel > 0) { // Realtime FIFO scheduling and all pages of Matlab/Octave locked into memory: schedulingparam.sched_priority = priorityLevel; priorityLevel = pthread_setschedparam(pthread_self(), SCHED_FIFO, &schedulingparam); if (priorityLevel == -1) { // Failed! if(!PsychPrefStateGet_SuppressAllWarnings()) { printf("PTB-ERROR: Failed to enable realtime-scheduling with Priority(%i) [%s]!\n", schedulingparam.sched_priority, strerror(errno)); if (errno==EPERM) { printf("PTB-ERROR: You need to run Matlab/Octave with root-privileges, or run the script PsychLinuxConfiguration once for this to work.\n"); } } errno=0; } else { // RT-Scheduling active. Lock all current and future memory: priorityLevel = mlockall(MCL_CURRENT | MCL_FUTURE); if (priorityLevel!=0) { // Failed! Report problem as warning, but don't worry further. if(!PsychPrefStateGet_SuppressAllWarnings()) printf("PTB-WARNING: Failed to enable system memory locking with Priority(%i) [%s]!\n", schedulingparam.sched_priority, strerror(errno)); // Undo any possibly partial mlocks.... munlockall(); errno=0; } } } else { // Standard scheduling and no memory locking: schedulingparam.sched_priority = 0; priorityLevel = pthread_setschedparam(pthread_self(), SCHED_OTHER, &schedulingparam); if (priorityLevel == -1) { // Failed! if(!PsychPrefStateGet_SuppressAllWarnings()) { printf("PTB-ERROR: Failed to disable realtime-scheduling with Priority(%i) [%s]!\n", schedulingparam.sched_priority, strerror(errno)); if (errno==EPERM) { printf("PTB-ERROR: You need to run Matlab/Octave with root-privileges, or run the script PsychLinuxConfiguration once for this to work.\n"); } } errno=0; } munlockall(); errno=0; } // End of setup of new Priority... } // End of Priority() helper for Linux. } } // End of special functions handling for Linux... #endif return(PsychError_none); }
PsychError PSYCHHIDGetCollections(void) { pRecDevice specDevice=NULL; UInt32 numDeviceElements; const char *elementFieldNames[]={"typeMaskName", "name", "deviceIndex", "collectionIndex", "typeValue", "typeName", "usagePageValue", "usageValue", "usageName", "memberCollectionIndices", "memberElementIndices"}; int i, numElementStructElements, numElementStructFieldNames=11, elementIndex, deviceIndex; PsychGenericScriptType *elementStruct, *memberCollectionIndicesMat, *memberIOElementIndicesMat; pRecElement currentElement; char elementTypeName[PSYCH_HID_MAX_DEVICE_ELEMENT_TYPE_NAME_LENGTH]; char usageName[PSYCH_HID_MAX_DEVICE_ELEMENT_USAGE_NAME_LENGTH]; char *typeMaskName; HIDElementTypeMask typeMask; pRecElement *memberCollectionRecords, *memberIOElementRecords; double *memberCollectionIndices, *memberIOElementIndices; int numSubCollections, numSubIOElements; PsychPushHelp(useString, synopsisString, seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; PsychErrorExit(PsychCapNumOutputArgs(1)); PsychErrorExit(PsychCapNumInputArgs(1)); PsychCopyInIntegerArg(1, TRUE, &deviceIndex); PsychHIDVerifyInit(); specDevice= PsychHIDGetDeviceRecordPtrFromIndex(deviceIndex); PsychHIDVerifyOpenDeviceInterfaceFromDeviceRecordPtr(specDevice); numDeviceElements= HIDCountDeviceElements(specDevice, kHIDElementTypeCollection); numElementStructElements = (int)numDeviceElements; PsychAllocOutStructArray(1, FALSE, numElementStructElements, numElementStructFieldNames, elementFieldNames, &elementStruct); elementIndex=0; for(currentElement=HIDGetFirstDeviceElement(specDevice,kHIDElementTypeCollection); currentElement != NULL; currentElement=HIDGetNextDeviceElement(currentElement, kHIDElementTypeCollection)) { typeMask=HIDConvertElementTypeToMask (currentElement->type); PsychHIDGetTypeMaskStringFromTypeMask(typeMask, &typeMaskName); PsychSetStructArrayStringElement("typeMaskName", elementIndex, typeMaskName, elementStruct); PsychSetStructArrayStringElement("name", elementIndex, currentElement->name, elementStruct); PsychSetStructArrayDoubleElement("deviceIndex", elementIndex, (double)deviceIndex, elementStruct); PsychSetStructArrayDoubleElement("collectionIndex", elementIndex, (double)elementIndex+1, elementStruct); PsychSetStructArrayDoubleElement("typeValue", elementIndex, (double)currentElement->type, elementStruct); HIDGetTypeName(currentElement->type, elementTypeName); PsychSetStructArrayStringElement("typeName", elementIndex, elementTypeName, elementStruct); PsychSetStructArrayDoubleElement("usagePageValue", elementIndex, (double)currentElement->usagePage, elementStruct); PsychSetStructArrayDoubleElement("usageValue", elementIndex, (double)currentElement->usage, elementStruct); HIDGetUsageName (currentElement->usagePage, currentElement->usage, usageName); PsychSetStructArrayStringElement("usageName", elementIndex, usageName, elementStruct); //find and return the indices of this collection's member collections and indices numSubCollections=PsychHIDCountCollectionElements(currentElement, kHIDElementTypeCollection); numSubIOElements=PsychHIDCountCollectionElements(currentElement, kHIDElementTypeIO); memberCollectionRecords=(pRecElement*)PsychMallocTemp(sizeof(pRecElement) * numSubCollections); memberIOElementRecords=(pRecElement*)PsychMallocTemp(sizeof(pRecElement) * numSubIOElements); PsychHIDFindCollectionElements(currentElement, kHIDElementTypeCollection, memberCollectionRecords, numSubCollections); PsychHIDFindCollectionElements(currentElement, kHIDElementTypeIO, memberIOElementRecords, numSubIOElements); memberCollectionIndices=NULL; PsychAllocateNativeDoubleMat(1, numSubCollections, 1, &memberCollectionIndices, &memberCollectionIndicesMat); memberIOElementIndices=NULL; PsychAllocateNativeDoubleMat(1, numSubIOElements, 1, &memberIOElementIndices, &memberIOElementIndicesMat); for(i=0;i<numSubCollections;i++) memberCollectionIndices[i]=PsychHIDGetIndexFromRecord(specDevice, memberCollectionRecords[i], kHIDElementTypeCollection); for(i=0;i<numSubIOElements;i++) memberIOElementIndices[i]=PsychHIDGetIndexFromRecord(specDevice, memberIOElementRecords[i], kHIDElementTypeIO); PsychFreeTemp(memberCollectionRecords); PsychFreeTemp(memberIOElementRecords); PsychSetStructArrayNativeElement("memberCollectionIndices", elementIndex, memberCollectionIndicesMat, elementStruct); PsychSetStructArrayNativeElement("memberElementIndices", elementIndex, memberIOElementIndicesMat, elementStruct); ++elementIndex; } return(PsychError_none); }
/* PsychCopyFontRecordToNativeStruct() Accept an array of pointers to psych font structures and the lenght of the array. Allocate and fill a native font struct array for the outside scripting environment */ void PsychCopyFontRecordsToNativeStructArray(int numFonts, PsychFontStructType **fontStructs, PsychGenericScriptType **fontStructArray) { int i, arrayIndex; PsychFontStructPtrType fontElement; PsychGenericScriptType *styleNameList; Str255 styleName; //for the outer font struct int numFontFieldNames=10; const char *fontFieldNames[]={"number", "name", "QuickDrawName", "PostScriptName", "familyName", "styleCode", "styleNames", "file", "metrics", "locale" }; //for the metrics meta struct int numMetaMetricsFieldNames=2; const char *metaMetricsFieldNames[]={"verticalMetrics", "horizontalMetrics"}; PsychGenericScriptType *metaMetrics; //for the metrics structs int numMetricsFieldNames=13; const char *metricsFieldNames[]={"ascent", "descent", "leading", "avgAdvanceWidth", "minLeftSideBearing", "minRightSideBearing", "stemWidth","stemHeight","capHeight","xHeight","italicAngle","underlinePosition","underlineThickness" }; PsychGenericScriptType *horizontalMetrics, *verticalMetrics; //for locale int numLocaleFieldNames=5; const char *localeFieldNames[]={"language", "languageVariant", "region", "regionVariant", "fullName"}; PsychGenericScriptType *locale; //convert the linked list of font structures to a struct array for the scripting environment. PsychAllocOutStructArray(kPsychNoArgReturn, FALSE, numFonts, numFontFieldNames, fontFieldNames, fontStructArray); for(arrayIndex=0; arrayIndex<numFonts; ++arrayIndex){ fontElement=fontStructs[arrayIndex]; PsychSetStructArrayDoubleElement("number", arrayIndex, fontElement->fontNumber, *fontStructArray); PsychSetStructArrayStringElement("name", arrayIndex, (char*) fontElement->fontFMName, *fontStructArray); PsychSetStructArrayStringElement("QuickDrawName", arrayIndex, (char*) fontElement->fontFamilyQuickDrawName, *fontStructArray); PsychSetStructArrayStringElement("PostScriptName", arrayIndex, (char*) fontElement->fontPostScriptName, *fontStructArray); PsychSetStructArrayStringElement("familyName", arrayIndex, (char*) fontElement->fontFMFamilyName, *fontStructArray); //style PsychSetStructArrayDoubleElement("styleCode", arrayIndex, (double)fontElement->fontFMStyle, *fontStructArray); PsychAllocOutCellVector(kPsychNoArgReturn, FALSE, fontElement->fontFMNumStyles, &styleNameList); for(i=0;i<fontElement->fontFMNumStyles;i++){ PsychGetFMFontStyleNameFromIndex(i, fontElement->fontFMStyle, (char*) styleName, 255); PsychSetCellVectorStringElement(i, (const char*) styleName, styleNameList); } PsychSetStructArrayNativeElement("styleNames", arrayIndex, styleNameList, *fontStructArray); PsychSetStructArrayStringElement("file", arrayIndex, fontElement->fontFile, *fontStructArray); //metrics PsychAllocOutStructArray(kPsychNoArgReturn, FALSE, 1, numMetaMetricsFieldNames, metaMetricsFieldNames, &metaMetrics); PsychAllocOutStructArray(kPsychNoArgReturn, FALSE, 1, numMetricsFieldNames, metricsFieldNames, &horizontalMetrics); PsychAllocOutStructArray(kPsychNoArgReturn, FALSE, 1, numMetricsFieldNames, metricsFieldNames, &verticalMetrics); //horizontal PsychSetStructArrayDoubleElement("ascent", 0, fontElement->horizontalMetrics.ascent, horizontalMetrics); PsychSetStructArrayDoubleElement("descent", 0, fontElement->horizontalMetrics.descent, horizontalMetrics); PsychSetStructArrayDoubleElement("leading", 0, fontElement->horizontalMetrics.leading, horizontalMetrics); PsychSetStructArrayDoubleElement("avgAdvanceWidth", 0, fontElement->horizontalMetrics.avgAdvanceWidth, horizontalMetrics); PsychSetStructArrayDoubleElement("minLeftSideBearing", 0, fontElement->horizontalMetrics.minLeftSideBearing, horizontalMetrics); PsychSetStructArrayDoubleElement("minRightSideBearing", 0, fontElement->horizontalMetrics.minRightSideBearing, horizontalMetrics); PsychSetStructArrayDoubleElement("stemWidth", 0, fontElement->horizontalMetrics.stemWidth, horizontalMetrics); PsychSetStructArrayDoubleElement("stemHeight", 0, fontElement->horizontalMetrics.stemHeight, horizontalMetrics); PsychSetStructArrayDoubleElement("capHeight", 0, fontElement->horizontalMetrics.capHeight, horizontalMetrics); PsychSetStructArrayDoubleElement("xHeight", 0, fontElement->horizontalMetrics.xHeight, horizontalMetrics); PsychSetStructArrayDoubleElement("italicAngle", 0, fontElement->horizontalMetrics.italicAngle, horizontalMetrics); PsychSetStructArrayDoubleElement("underlinePosition", 0, fontElement->horizontalMetrics.underlinePosition, horizontalMetrics); PsychSetStructArrayDoubleElement("underlineThickness", 0, fontElement->horizontalMetrics.underlineThickness, horizontalMetrics); //vertical PsychSetStructArrayDoubleElement("ascent", 0, fontElement->verticalMetrics.ascent, verticalMetrics); PsychSetStructArrayDoubleElement("descent", 0, fontElement->verticalMetrics.descent, verticalMetrics); PsychSetStructArrayDoubleElement("leading", 0, fontElement->verticalMetrics.leading, verticalMetrics); PsychSetStructArrayDoubleElement("avgAdvanceWidth", 0, fontElement->verticalMetrics.avgAdvanceWidth, verticalMetrics); PsychSetStructArrayDoubleElement("minLeftSideBearing", 0, fontElement->verticalMetrics.minLeftSideBearing, verticalMetrics); PsychSetStructArrayDoubleElement("minRightSideBearing", 0, fontElement->verticalMetrics.minRightSideBearing, verticalMetrics); PsychSetStructArrayDoubleElement("stemWidth", 0, fontElement->verticalMetrics.stemWidth, verticalMetrics); PsychSetStructArrayDoubleElement("stemHeight", 0, fontElement->verticalMetrics.stemHeight, verticalMetrics); PsychSetStructArrayDoubleElement("capHeight", 0, fontElement->verticalMetrics.capHeight, verticalMetrics); PsychSetStructArrayDoubleElement("xHeight", 0, fontElement->verticalMetrics.xHeight, verticalMetrics); PsychSetStructArrayDoubleElement("italicAngle", 0, fontElement->verticalMetrics.italicAngle, verticalMetrics); PsychSetStructArrayDoubleElement("underlinePosition", 0, fontElement->verticalMetrics.underlinePosition, verticalMetrics); PsychSetStructArrayDoubleElement("underlineThickness", 0, fontElement->verticalMetrics.underlineThickness, verticalMetrics); PsychSetStructArrayNativeElement("horizontalMetrics", 0, horizontalMetrics, metaMetrics); PsychSetStructArrayNativeElement("verticalMetrics", 0, verticalMetrics, metaMetrics); PsychSetStructArrayNativeElement("metrics", arrayIndex, metaMetrics, *fontStructArray); //locale PsychAllocOutStructArray(kPsychNoArgReturn, FALSE, 1, numLocaleFieldNames, localeFieldNames, &locale); PsychSetStructArrayStringElement("language", 0, (char*) fontElement->locale.language, locale); PsychSetStructArrayStringElement("languageVariant", 0, (char*) fontElement->locale.languageVariant, locale); PsychSetStructArrayStringElement("region", 0, (char*) fontElement->locale.region, locale); PsychSetStructArrayStringElement("regionVariant", 0, (char*) fontElement->locale.regionVariant, locale); PsychSetStructArrayStringElement("fullName", 0, (char*) fontElement->locale.fullName, locale); PsychSetStructArrayNativeElement("locale", arrayIndex, locale, *fontStructArray); } }
PsychError PSYCHHIDGetElements(void) { pRecDevice specDevice=NULL; UInt32 numDeviceElements; const char *elementFieldNames[]={"typeMaskName", "name", "deviceIndex", "elementIndex", "typeValue", "typeName", "usagePageValue", "usageValue", "usageName", "dataSize", "rangeMin", "rangeMax", "scaledRangeMin", "scaledRangeMax", "relative", "wrapping", "nonLinear", "preferredState", "nullState", "calMin", "calMax", "scalingMin", "scalingMax"}; int numElementStructElements, numElementStructFieldNames=23, elementIndex, deviceIndex; PsychGenericScriptType *elementStruct; pRecElement currentElement; char elementTypeName[PSYCH_HID_MAX_DEVICE_ELEMENT_TYPE_NAME_LENGTH]; char usageName[PSYCH_HID_MAX_DEVICE_ELEMENT_USAGE_NAME_LENGTH]; char *typeMaskName; HIDElementTypeMask typeMask; //all subfunctions should have these two lines PsychPushHelp(useString, synopsisString, seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; PsychErrorExit(PsychCapNumOutputArgs(1)); PsychErrorExit(PsychCapNumInputArgs(1)); PsychCopyInIntegerArg(1, TRUE, &deviceIndex); PsychHIDVerifyInit(); specDevice= PsychHIDGetDeviceRecordPtrFromIndex(deviceIndex); PsychHIDVerifyOpenDeviceInterfaceFromDeviceRecordPtr(specDevice); numDeviceElements= HIDCountDeviceElements(specDevice, kHIDElementTypeIO); numElementStructElements = (int)numDeviceElements; PsychAllocOutStructArray(1, FALSE, numElementStructElements, numElementStructFieldNames, elementFieldNames, &elementStruct); elementIndex=0; for(currentElement=HIDGetFirstDeviceElement(specDevice,kHIDElementTypeIO); currentElement != NULL; currentElement=HIDGetNextDeviceElement(currentElement, kHIDElementTypeIO)) { typeMask=HIDConvertElementTypeToMask (currentElement->type); PsychHIDGetTypeMaskStringFromTypeMask(typeMask, &typeMaskName); PsychSetStructArrayStringElement("typeMaskName", elementIndex, typeMaskName, elementStruct); PsychSetStructArrayStringElement("name", elementIndex, currentElement->name, elementStruct); PsychSetStructArrayDoubleElement("deviceIndex", elementIndex, (double)deviceIndex, elementStruct); PsychSetStructArrayDoubleElement("elementIndex", elementIndex, (double)elementIndex+1, elementStruct); PsychSetStructArrayDoubleElement("typeValue", elementIndex, (double)currentElement->type, elementStruct); HIDGetTypeName(currentElement->type, elementTypeName); PsychSetStructArrayStringElement("typeName", elementIndex, elementTypeName, elementStruct); PsychSetStructArrayDoubleElement("usagePageValue", elementIndex, (double)currentElement->usagePage, elementStruct); PsychSetStructArrayDoubleElement("usageValue", elementIndex, (double)currentElement->usage, elementStruct); HIDGetUsageName (currentElement->usagePage, currentElement->usage, usageName); PsychSetStructArrayStringElement("usageName", elementIndex, usageName, elementStruct); PsychSetStructArrayDoubleElement("dataSize", elementIndex, (double)currentElement->size, elementStruct); PsychSetStructArrayDoubleElement("rangeMin", elementIndex, (double)currentElement->min, elementStruct); PsychSetStructArrayDoubleElement("rangeMax", elementIndex, (double)currentElement->max, elementStruct); PsychSetStructArrayDoubleElement("scaledRangeMin", elementIndex, (double)currentElement->scaledMin, elementStruct); PsychSetStructArrayDoubleElement("scaledRangeMax", elementIndex, (double)currentElement->scaledMax, elementStruct); PsychSetStructArrayDoubleElement("relative", elementIndex, (double)currentElement->relative, elementStruct); //psych_bool flag PsychSetStructArrayDoubleElement("wrapping", elementIndex, (double)currentElement->wrapping, elementStruct); //psych_bool flag PsychSetStructArrayDoubleElement("nonLinear", elementIndex, (double)currentElement->nonLinear, elementStruct); //psych_bool flag PsychSetStructArrayDoubleElement("preferredState", elementIndex, (double)currentElement->preferredState, elementStruct); //psych_bool flag PsychSetStructArrayDoubleElement("nullState", elementIndex, (double)currentElement->nullState, elementStruct); //psych_bool flag PsychSetStructArrayDoubleElement("calMin", elementIndex, (double)currentElement->calMin, elementStruct); PsychSetStructArrayDoubleElement("calMax", elementIndex, (double)currentElement->calMax, elementStruct); PsychSetStructArrayDoubleElement("scalingMin", elementIndex, (double)currentElement->userMin, elementStruct); PsychSetStructArrayDoubleElement("scalingMax", elementIndex, (double)currentElement->userMax, elementStruct); ++elementIndex; } return(PsychError_none); }
PsychError SCREENGetWindowInfo(void) { const char *FieldNames[]={ "Beamposition", "LastVBLTimeOfFlip", "LastVBLTime", "VBLCount", "StereoMode", "ImagingMode", "MultiSampling", "MissedDeadlines", "StereoDrawBuffer", "GuesstimatedMemoryUsageMB", "VBLStartline", "VBLEndline", "VideoRefreshFromBeamposition", "GLVendor", "GLRenderer", "GLVersion", "GLSupportsFBOUpToBpc", "GLSupportsBlendingUpToBpc", "GLSupportsTexturesUpToBpc", "GLSupportsFilteringUpToBpc", "GLSupportsPrecisionColors", "GLSupportsFP32Shading", "BitsPerColorComponent" }; const int fieldCount = 23; PsychGenericScriptType *s; PsychWindowRecordType *windowRecord; double beamposition, lastvbl; int beamposonly = 0; CGDirectDisplayID displayId; psych_uint64 postflip_vblcount; double vbl_startline; long scw, sch; bool onscreen; //all subfunctions should have these two lines. 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(1)); //The maximum number of outputs // Get the window record: PsychAllocInWindowRecordArg(kPsychUseDefaultArgPosition, TRUE, &windowRecord); onscreen = PsychIsOnscreenWindow(windowRecord); // Query beamposonly flag: Defaults to zero. PsychCopyInIntegerArg(2, FALSE, &beamposonly); if (onscreen) { // Query rasterbeam position: Will return -1 if unsupported. PsychGetCGDisplayIDFromScreenNumber(&displayId, windowRecord->screenNumber); beamposition = (double) PsychGetDisplayBeamPosition(displayId, windowRecord->screenNumber); } else { beamposition = -1; } if (beamposonly) { // Return the measured beamposition: PsychCopyOutDoubleArg(1, FALSE, beamposition); } else { // Return all information: PsychAllocOutStructArray(1, FALSE, 1, fieldCount, FieldNames, &s); // Rasterbeam position: PsychSetStructArrayDoubleElement("Beamposition", 0, beamposition, s); // Time of last vertical blank when a double-buffer swap occured: PsychSetStructArrayDoubleElement("LastVBLTimeOfFlip", 0, windowRecord->time_at_last_vbl, s); // Try to determine system time of last VBL on display, independent of any // flips / bufferswaps. lastvbl = -1; postflip_vblcount = 0; #if PSYCH_SYSTEM == PSYCH_OSX // On OS/X we can query the OS for the system time of last VBL, so we can // use the most recent VBL timestamp as baseline for timing calculations, // instead of one far in the past. if (onscreen) { lastvbl = PsychOSGetVBLTimeAndCount(windowRecord->screenNumber, &postflip_vblcount); } #endif // If we couldn't determine this information we just set lastvbl to the last known // vbl timestamp of last flip -- better than nothing... if (lastvbl < 0) lastvbl = windowRecord->time_at_last_vbl; PsychSetStructArrayDoubleElement("LastVBLTime", 0, lastvbl, s); PsychSetStructArrayDoubleElement("VBLCount", 0, (double) postflip_vblcount, s); // Misc. window parameters: PsychSetStructArrayDoubleElement("StereoMode", 0, windowRecord->stereomode, s); PsychSetStructArrayDoubleElement("ImagingMode", 0, windowRecord->imagingMode, s); PsychSetStructArrayDoubleElement("MultiSampling", 0, windowRecord->multiSample, s); PsychSetStructArrayDoubleElement("MissedDeadlines", 0, windowRecord->nr_missed_deadlines, s); PsychSetStructArrayDoubleElement("StereoDrawBuffer", 0, windowRecord->stereodrawbuffer, s); PsychSetStructArrayDoubleElement("GuesstimatedMemoryUsageMB", 0, (double) windowRecord->surfaceSizeBytes / 1024 / 1024, s); PsychSetStructArrayDoubleElement("BitsPerColorComponent", 0, (double) windowRecord->bpc, s); // Query real size of the underlying display in order to define the vbl_startline: PsychGetScreenSize(windowRecord->screenNumber, &scw, &sch); vbl_startline = (double) sch; PsychSetStructArrayDoubleElement("VBLStartline", 0, vbl_startline, s); // And VBL endline: PsychSetStructArrayDoubleElement("VBLEndline", 0, windowRecord->VBL_Endline, s); // Video refresh interval duration from beamposition method: PsychSetStructArrayDoubleElement("VideoRefreshFromBeamposition", 0, windowRecord->ifi_beamestimate, s); // Renderer information: PsychSetDrawingTarget(windowRecord); PsychSetStructArrayStringElement("GLVendor", 0, glGetString(GL_VENDOR), s); PsychSetStructArrayStringElement("GLRenderer", 0, glGetString(GL_RENDERER), s); PsychSetStructArrayStringElement("GLVersion", 0, glGetString(GL_VERSION), s); // FBO's supported, and how deep? if (windowRecord->gfxcaps & kPsychGfxCapFBO) { if (windowRecord->gfxcaps & kPsychGfxCapFPFBO32) { PsychSetStructArrayDoubleElement("GLSupportsFBOUpToBpc", 0, 32, s); } else if (windowRecord->gfxcaps & kPsychGfxCapFPFBO16) { PsychSetStructArrayDoubleElement("GLSupportsFBOUpToBpc", 0, 16, s); } else PsychSetStructArrayDoubleElement("GLSupportsFBOUpToBpc", 0, 8, s); } else { PsychSetStructArrayDoubleElement("GLSupportsFBOUpToBpc", 0, 0, s); } // How deep is alpha blending supported? if (windowRecord->gfxcaps & kPsychGfxCapFPBlend32) { PsychSetStructArrayDoubleElement("GLSupportsBlendingUpToBpc", 0, 32, s); } else if (windowRecord->gfxcaps & kPsychGfxCapFPBlend16) { PsychSetStructArrayDoubleElement("GLSupportsBlendingUpToBpc", 0, 16, s); } else PsychSetStructArrayDoubleElement("GLSupportsBlendingUpToBpc", 0, 8, s); // How deep is texture mapping supported? if (windowRecord->gfxcaps & kPsychGfxCapFPTex32) { PsychSetStructArrayDoubleElement("GLSupportsTexturesUpToBpc", 0, 32, s); } else if (windowRecord->gfxcaps & kPsychGfxCapFPTex16) { PsychSetStructArrayDoubleElement("GLSupportsTexturesUpToBpc", 0, 16, s); } else PsychSetStructArrayDoubleElement("GLSupportsTexturesUpToBpc", 0, 8, s); // How deep is texture filtering supported? if (windowRecord->gfxcaps & kPsychGfxCapFPFilter32) { PsychSetStructArrayDoubleElement("GLSupportsFilteringUpToBpc", 0, 32, s); } else if (windowRecord->gfxcaps & kPsychGfxCapFPFilter16) { PsychSetStructArrayDoubleElement("GLSupportsFilteringUpToBpc", 0, 16, s); } else PsychSetStructArrayDoubleElement("GLSupportsFilteringUpToBpc", 0, 8, s); if (windowRecord->gfxcaps & kPsychGfxCapVCGood) { PsychSetStructArrayDoubleElement("GLSupportsPrecisionColors", 0, 1, s); } else PsychSetStructArrayDoubleElement("GLSupportsPrecisionColors", 0, 0, s); if (windowRecord->gfxcaps & kPsychGfxCapFP32Shading) { PsychSetStructArrayDoubleElement("GLSupportsFP32Shading", 0, 1, s); } else PsychSetStructArrayDoubleElement("GLSupportsFP32Shading", 0, 0, s); } // Done. return(PsychError_none); }
int PsychHIDReturnEventFromEventBuffer(int deviceIndex, int outArgIndex, double maxWaitTimeSecs) { unsigned int navail, j; PsychHIDEventRecord evt; PsychGenericScriptType *retevent; double* foo = NULL; PsychGenericScriptType *outMat; double *v; const char *FieldNames[] = { "Type", "Time", "Pressed", "Keycode", "CookedKey", "ButtonStates", "Motion", "X", "Y", "NormX", "NormY", "Valuators" }; if (deviceIndex < 0) deviceIndex = PsychHIDGetDefaultKbQueueDevice(); if (!hidEventBuffer[deviceIndex]) return(0); PsychLockMutex(&hidEventBufferMutex[deviceIndex]); navail = hidEventBufferWritePos[deviceIndex] - hidEventBufferReadPos[deviceIndex]; // If nothing available and we're asked to wait for something, then wait: if ((navail == 0) && (maxWaitTimeSecs > 0)) { // Wait for something: PsychTimedWaitCondition(&hidEventBufferCondition[deviceIndex], &hidEventBufferMutex[deviceIndex], maxWaitTimeSecs); // Recompute number of available events: navail = hidEventBufferWritePos[deviceIndex] - hidEventBufferReadPos[deviceIndex]; } // Check if anything available, copy it if so: if (navail) { memcpy(&evt, &(hidEventBuffer[deviceIndex][hidEventBufferReadPos[deviceIndex] % hidEventBufferCapacity[deviceIndex]]), sizeof(PsychHIDEventRecord)); hidEventBufferReadPos[deviceIndex]++; } PsychUnlockMutex(&hidEventBufferMutex[deviceIndex]); if (navail) { // Return event struct: switch (evt.type) { case 0: // Press/Release case 1: // Motion/Valuator change PsychAllocOutStructArray(outArgIndex, kPsychArgOptional, 1, 12, FieldNames, &retevent); break; case 2: // Touch begin case 3: // Touch update/move case 4: // Touch end case 5: // Touch sequence compromised marker. If this one shows up - with magic touch point // id 0xffffffff btw., then the user script knows the sequence was cut short / aborted // by some higher priority consumer, e.g., some global gesture recognizer. PsychAllocOutStructArray(outArgIndex, kPsychArgOptional, 1, 12, FieldNames, &retevent); break; default: PsychErrorExitMsg(PsychError_internal, "Unhandled keyboard queue event type!"); } PsychSetStructArrayDoubleElement("Type", 0, (double) evt.type, retevent); PsychSetStructArrayDoubleElement("Time", 0, evt.timestamp, retevent); PsychSetStructArrayDoubleElement("Pressed", 0, (double) (evt.status & (1 << 0)) ? 1 : 0, retevent); PsychSetStructArrayDoubleElement("Keycode", 0, (double) evt.rawEventCode, retevent); PsychSetStructArrayDoubleElement("CookedKey", 0, (double) evt.cookedEventCode, retevent); PsychSetStructArrayDoubleElement("ButtonStates", 0, (double) evt.buttonStates, retevent); PsychSetStructArrayDoubleElement("Motion", 0, (double) (evt.status & (1 << 1)) ? 1 : 0, retevent); PsychSetStructArrayDoubleElement("X", 0, (double) evt.X, retevent); PsychSetStructArrayDoubleElement("Y", 0, (double) evt.Y, retevent); PsychSetStructArrayDoubleElement("NormX", 0, (double) evt.normX, retevent); PsychSetStructArrayDoubleElement("NormY", 0, (double) evt.normY, retevent); // Copy out all valuators (including redundant (X,Y) again: PsychAllocateNativeDoubleMat(1, evt.numValuators, 1, &v, &outMat); for (j = 0; j < evt.numValuators; j++) *(v++) = (double) evt.valuators[j]; PsychSetStructArrayNativeElement("Valuators", 0, outMat, retevent); return(navail - 1); } else { // Return empty matrix: PsychCopyOutDoubleMatArg(outArgIndex, kPsychArgOptional, 0, 0, 0, foo); return(0); } }
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); }
PsychError MODULEVersion(void) { int i; PsychAuthorDescriptorType *author; const char *versionFieldNames[]={"version", "major", "minor", "point", "build", "date", "time", "module", "project", "os", "language", "authors"}; const char *authorFiledNames[]={"first", "middle", "last", "initials", "email", "url"}; char *versionString; int buildNumber; int numVersionFieldDimensions=1, numVersionFieldNames=12, numAuthorFieldNames=6, numAuthors; PsychGenericScriptType *versionStructArray, *authorStructArray; //we ignore the usual usage help strings and create our own based on the module name. MODULEVersion() is for use by any Psychtoolbox module. char useString[256], synopsisString[256], *moduleName; char useStringP1[]="struct="; char useStringP2[]="('Version')"; char synopsisStringP1[]="return the version of "; char synopsisStringP2[]=" in a struct"; //for generic usage we modifiy at runtiome the help string to replace "Screen" with the name of this module. moduleName=PsychGetModuleName(); useString[0]='\0'; strcat(useString, useStringP1); strcat(useString, moduleName); strcat(useString, useStringP2); synopsisString[0]='\0'; strcat(synopsisString, synopsisStringP1); strcat(synopsisString, moduleName); strcat(synopsisString, synopsisStringP2); PsychPushHelp(useString, synopsisString, seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; //check to see if the user supplied superfluous arguments PsychErrorExit(PsychCapNumOutputArgs(1)); PsychErrorExit(PsychCapNumInputArgs(0)); //get the build and version string buildNumber=PsychGetBuildNumber(); versionString=PsychGetVersionString(); //create a structure and populate it. PsychAllocOutStructArray(1, FALSE, numVersionFieldDimensions, numVersionFieldNames, versionFieldNames, &versionStructArray); PsychSetStructArrayStringElement("version", 0, versionString, versionStructArray); PsychSetStructArrayDoubleElement("major", 0, (double)PsychGetMajorVersionNumber(), versionStructArray); PsychSetStructArrayDoubleElement("minor", 0, (double)PsychGetMinorVersionNumber(), versionStructArray); PsychSetStructArrayDoubleElement("point", 0, (double)PsychGetPointVersionNumber(), versionStructArray); PsychSetStructArrayDoubleElement("build", 0, buildNumber, versionStructArray); PsychSetStructArrayStringElement("date", 0, PsychGetBuildDate(), versionStructArray); PsychSetStructArrayStringElement("time", 0, PsychGetBuildTime(), versionStructArray); PsychSetStructArrayStringElement("module", 0, moduleName, versionStructArray); PsychSetStructArrayStringElement("project", 0, PSYCHTOOLBOX_PROJECT_NAME, versionStructArray); PsychSetStructArrayStringElement("os", 0, PSYCHTOOLBOX_OS_NAME, versionStructArray); PsychSetStructArrayStringElement("language", 0, PSYCHTOOLBOX_SCRIPTING_LANGUAGE_NAME, versionStructArray); numAuthors=PsychGetNumModuleAuthors(); PsychAllocOutStructArray(-1, FALSE, numAuthors, numAuthorFieldNames, authorFiledNames, &authorStructArray); for(i=0;i<numAuthors;i++){ GetModuleAuthorDescriptorFromIndex(i, &author); PsychSetStructArrayStringElement("first", i, author->firstName, authorStructArray); PsychSetStructArrayStringElement("middle", i, author->middleName, authorStructArray); PsychSetStructArrayStringElement("last", i, author->lastName, authorStructArray); PsychSetStructArrayStringElement("initials", i, author->initials, authorStructArray); PsychSetStructArrayStringElement("email", i, author->email, authorStructArray); PsychSetStructArrayStringElement("url", i, author->url, authorStructArray); } PsychSetStructArrayStructElement("authors",0, authorStructArray, versionStructArray); return(PsychError_none); }
PsychError PSYCHHIDGetDevices(void) { pRecDevice currentDevice=NULL; const char *deviceFieldNames[]={"usagePageValue", "usageValue", "usageName", "index", "transport", "vendorID", "productID", "version", "manufacturer", "product", "serialNumber", "locationID", "totalElements", "features", "inputs", "outputs", "collections", "axes", "buttons", "hats", "sliders", "dials", "wheels"}; int numDeviceStructElements, numDeviceStructFieldNames=23, deviceIndex; PsychGenericScriptType *deviceStruct; char usageName[PSYCH_HID_MAX_DEVICE_ELEMENT_USAGE_NAME_LENGTH]; PsychPushHelp(useString, synopsisString, seeAlsoString); if(PsychIsGiveHelp()){PsychGiveHelp();return(PsychError_none);}; PsychErrorExit(PsychCapNumOutputArgs(1)); PsychErrorExit(PsychCapNumInputArgs(0)); PsychHIDVerifyInit(); numDeviceStructElements=(int)HIDCountDevices(); PsychAllocOutStructArray(1, FALSE, numDeviceStructElements, numDeviceStructFieldNames, deviceFieldNames, &deviceStruct); deviceIndex=0; for(currentDevice=HIDGetFirstDevice(); currentDevice != NULL; currentDevice=HIDGetNextDevice(currentDevice)){ PsychSetStructArrayDoubleElement("usagePageValue", deviceIndex, (double)currentDevice->usagePage, deviceStruct); PsychSetStructArrayDoubleElement("usageValue", deviceIndex, (double)currentDevice->usage, deviceStruct); HIDGetUsageName (currentDevice->usagePage, currentDevice->usage, usageName); PsychSetStructArrayStringElement("usageName", deviceIndex, usageName, deviceStruct); PsychSetStructArrayDoubleElement("index", deviceIndex, (double)deviceIndex+1, deviceStruct); PsychSetStructArrayStringElement("transport", deviceIndex, currentDevice->transport, deviceStruct); PsychSetStructArrayDoubleElement("vendorID", deviceIndex, (double)currentDevice->vendorID, deviceStruct); PsychSetStructArrayDoubleElement("productID", deviceIndex, (double)currentDevice->productID, deviceStruct); PsychSetStructArrayDoubleElement("version", deviceIndex, (double)currentDevice->version, deviceStruct); PsychSetStructArrayStringElement("manufacturer", deviceIndex, currentDevice->manufacturer, deviceStruct); PsychSetStructArrayStringElement("product", deviceIndex, currentDevice->product, deviceStruct); PsychSetStructArrayStringElement("serialNumber", deviceIndex, currentDevice->serial, deviceStruct); PsychSetStructArrayDoubleElement("locationID", deviceIndex, (double)currentDevice->locID, deviceStruct); PsychSetStructArrayDoubleElement("totalElements", deviceIndex, (double)currentDevice->totalElements, deviceStruct); PsychSetStructArrayDoubleElement("features", deviceIndex, (double)currentDevice->features, deviceStruct); PsychSetStructArrayDoubleElement("inputs", deviceIndex, (double)currentDevice->inputs, deviceStruct); PsychSetStructArrayDoubleElement("outputs", deviceIndex, (double)currentDevice->outputs, deviceStruct); PsychSetStructArrayDoubleElement("collections", deviceIndex, (double)currentDevice->collections, deviceStruct); PsychSetStructArrayDoubleElement("axes", deviceIndex, (double)currentDevice->axis, deviceStruct); PsychSetStructArrayDoubleElement("buttons", deviceIndex, (double)currentDevice->buttons, deviceStruct); PsychSetStructArrayDoubleElement("hats", deviceIndex, (double)currentDevice->hats, deviceStruct); PsychSetStructArrayDoubleElement("sliders", deviceIndex, (double)currentDevice->sliders, deviceStruct); PsychSetStructArrayDoubleElement("dials", deviceIndex, (double)currentDevice->dials, deviceStruct); PsychSetStructArrayDoubleElement("wheels", deviceIndex, (double)currentDevice->wheels, deviceStruct); ++deviceIndex; } return(PsychError_none); }