File: StoreBit.c

package info (click to toggle)
psychtoolbox-3 3.0.19.14.dfsg1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 86,796 kB
  • sloc: ansic: 176,245; cpp: 20,103; objc: 5,393; sh: 2,753; python: 1,397; php: 384; makefile: 193; java: 113
file content (207 lines) | stat: -rw-r--r-- 8,637 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
/*
	PsychSourceGL/Source/Experiments/StoreBit/StoreBit.c		
  
	PROJECTS: 
  
		StoreBit only
  
	AUTHORS:
  
		Allen.Ingling@nyu.edu		awi 
  
	PLATFORMS:	
  
		Only OS X.
    
	HISTORY:

		9/7/05		awi		Wrote it.
		1/1/27		awi		Changed bundle name back to StoreBitBundle.  It had been changed to getchar while testing that.
		


*/


#include "StoreBit.h"


static void	LoadPrivateFrameworkBundle( CFStringRef framework, CFBundleRef *bundlePtr );

typedef void 	(*InitializeCocoaProc)(void);
typedef	void	(*CocoaStoreBitProc)(Boolean newValue);
typedef Boolean (*CocoaGetBitProc)(void);
typedef void	(*CocoaFreeBitProc)(void);
typedef void	(*CocoaGetWindowCharacterProc)(char *charStringLen2, double *readTime);

CocoaStoreBitProc				CocoaStoreBit=NULL;
CocoaGetBitProc					CocoaGetBit=NULL;
CocoaFreeBitProc				CocoaFreeBit=NULL;
CocoaGetWindowCharacterProc		CocoaGetWindowCharacter=NULL;

static		CFBundleRef			gStoreBitLibBundle;		//	"StoreBitLib.bundle" 


PsychError STOREBITStoreBit(void) 
{
	static Boolean				firstTime=TRUE;
	static Boolean				failedToLoadFlag=FALSE;
    double						returnValue, inputValue;
	static						Boolean cBit=FALSE;
	Boolean						isThere, inputValueBoolean;
	InitializeCocoaProc			CocoaInitializeCocoa;
	char						readChar[2];
	double						readTime;
	const char					*thisMexFunctionName;
//	#define						MAX_MATLAB_CALL_STRING_LENGTH	1024;
//	char						matlabCallString[MAX_MATLAB_CALL_STRING_LENGTH];
	int							matlabCallbackErrorFlag, errorFlag;
	mxArray						*matlabCallbackOutputs, *matlabCallbackInputs[1];
	#define						COCOA_BUNDLE_NAME					"StoreBitLib.bundle"
	#define						SYSTEM_FILE_PATH_SEPARATOR			"/"
	CFStringRef					directoryPathCFString, bundlePathCFString;
	char						*pathToBundleDirectoryStr;
	size_t						pathToBundleDirectoryStrSizeBytes, pathToBundleDirectoryStrSizeChars, bundleNameStrSizeChars, pathToBundleStrSizeChars, charSize, mxCharSize;
	CFStringRef					stringArray[3];
	CFArrayRef					stringCFArray;


	if(failedToLoadFlag){
		//In case we re-enter this mex file and the previous call failed to the load the bundle, then notifiy and exit.
		//The user will have to clear mex to reset, but that's not too high a penalty for a rare and serious problem like a missing library.
		PsychErrorExitMsg(PsychError_internal,"Failed to load the Cocoa Bundle \"StoreBitLib.bundle\".");
	}else{
		if(firstTime){
			firstTime=FALSE;
			//we assume that the bundle is in the same directory as the mex file itself.  
			// We break the PsychScriptingGlue API here by calling a mex API function here directly. Eventually these calls which get the path to this 
			// mex file should be grouped into their function in the scripting glue layer.  We could also make the 0th input argument the function name.
			thisMexFunctionName= mexFunctionName();
			matlabCallbackInputs[0]= mxCreateString(thisMexFunctionName);
			matlabCallbackErrorFlag=mexCallMATLAB(1, &matlabCallbackOutputs, 1, matlabCallbackInputs, "FunctionFolder");
			if(matlabCallbackErrorFlag){
				failedToLoadFlag=TRUE;
				PsychErrorExitMsg(PsychError_internal,"MATLAB callback to \"FunctionFolder.m\" failed.  It could be missing or off the MATLAB path.");
			}
			if(mxGetM(matlabCallbackOutputs) * mxGetN(matlabCallbackOutputs) == 0){
				failedToLoadFlag=TRUE;
				PsychErrorExitMsg(PsychError_internal,"MATLAB callback to \"FunctionFolder.m\" failed.");
			}
			pathToBundleDirectoryStrSizeBytes= (size_t)((mxGetM(matlabCallbackOutputs) * mxGetN(matlabCallbackOutputs) + 1)* sizeof(mxChar));
			pathToBundleDirectoryStr=(char*)malloc(pathToBundleDirectoryStrSizeBytes);
			errorFlag= mxGetString(matlabCallbackOutputs, (char*)pathToBundleDirectoryStr, pathToBundleDirectoryStrSizeBytes);
			if(errorFlag){
				free((void*)pathToBundleDirectoryStr);
				failedToLoadFlag=TRUE;
				PsychErrorExitMsg(PsychError_internal,"Failed to load the Cocoa Bundle because we could not convernt a MATALB string to C string.");
			}
			//now we have in a unicode string the name of the directory in which this mex function, and also presumably its associated bundle reside.  
			//next, get convert it to a CF string and append to that string a path seperator and the name of the bundle.  
			//directoryPathCFString= CFStringCreateWithCharacters(kCFAllocatorDefault, (UniChar*)pathToBundleDirectoryStr, mxGetM(matlabCallbackOutputs) * mxGetN(matlabCallbackOutputs));
//			stringArray[0]= CFStringCreateWithCString(kCFAllocatorDefault, pathToBundleDirectoryStr, kCFStringEncodingUnicode);		// the path to the directory
			stringArray[0]= CFStringCreateWithCString(kCFAllocatorDefault, pathToBundleDirectoryStr, kCFStringEncodingUTF8);		// the path to the directory
			stringArray[1]= CFSTR(SYSTEM_FILE_PATH_SEPARATOR);
			stringArray[2]= CFSTR(COCOA_BUNDLE_NAME);
			stringCFArray= CFArrayCreate(kCFAllocatorDefault, (void*)stringArray, 3, &kCFTypeArrayCallBacks);
			bundlePathCFString= CFStringCreateByCombiningStrings(kCFAllocatorDefault, stringCFArray, CFSTR(""));
			
//			LoadPrivateFrameworkBundle( CFSTR("/StoreBitLib.bundle"), &gStoreBitLibBundle );
//			LoadPrivateFrameworkBundle( CFSTR("/Applications/Psychtoolbox/PsychDemos/StoreBitLib.bundle"), &gStoreBitLibBundle );
			LoadPrivateFrameworkBundle(bundlePathCFString , &gStoreBitLibBundle );
			CFRelease(bundlePathCFString);
			CFRelease(stringArray[0]);
			CFRelease(stringCFArray);
			free((void*)pathToBundleDirectoryStr);
			if ( gStoreBitLibBundle == NULL ){
				failedToLoadFlag=TRUE;
				PsychErrorExitMsg(PsychError_internal,"Failed to load the Cocoa Bundle \"StoreBitLib.bundle\".  It could be missing.");
			}
			
			CocoaInitializeCocoa = (InitializeCocoaProc) CFBundleGetFunctionPointerForName(gStoreBitLibBundle, CFSTR("InitializeCocoa") );
			if(CocoaInitializeCocoa != NULL) 
				CocoaInitializeCocoa();
			CocoaStoreBit= (CocoaStoreBitProc)CFBundleGetFunctionPointerForName(gStoreBitLibBundle, CFSTR("CocoaStoreBit"));
			CocoaGetBit= (CocoaGetBitProc)CFBundleGetFunctionPointerForName(gStoreBitLibBundle, CFSTR("CocoaGetBit"));
			CocoaFreeBit= (CocoaFreeBitProc)CFBundleGetFunctionPointerForName(gStoreBitLibBundle, CFSTR("CocoaFreeBit"));
			CocoaGetWindowCharacter= (CocoaGetWindowCharacterProc)CFBundleGetFunctionPointerForName(gStoreBitLibBundle, CFSTR("CocoaGetWindowCharacter"));
		}//  if(firstTime){
					
		//check to see if the user supplied superfluous arguments
		PsychErrorExit(PsychCapNumOutputArgs(1));
		PsychErrorExit(PsychCapNumInputArgs(1));
		
		//Allocate a return matrix and load it with the depth values.
		returnValue=(double)CocoaGetBit();
		PsychCopyOutDoubleArg(1, kPsychArgOptional, returnValue);
		isThere=PsychCopyInDoubleArg(1, kPsychArgOptional, &inputValue);
		if(isThere){
			inputValueBoolean=(Boolean)inputValue;
			CocoaStoreBit(inputValueBoolean);
		}
//		CocoaGetWindowCharacter(readChar, &readTime);
//		mexPrintf("%s\n", readChar);
//		mexPrintf("%d\n", readTime);
	}
	
    return(PsychError_none);	
}



/*
	LoadPrivateFrameworkBundle
	
	Modified from Apple's version to accept an absolute path in posix style.  Apple's version assumed
	that the private bundled framework resided within the calling application's bundle.  We want this to
	work with MATLAB which is not distributed as an application bundle.
*/ 
static void	LoadPrivateFrameworkBundle( CFStringRef framework, CFBundleRef *bundlePtr )
{
	CFURLRef	baseURL			= NULL;
	CFURLRef	bundleURL		= NULL;
	CFBundleRef	myAppsBundle	= NULL;
	
	if ( bundlePtr == NULL )	goto Bail;
	*bundlePtr = NULL;
	
	myAppsBundle	= CFBundleGetMainBundle();					//	Get our application's main bundle from Core Foundation
	if ( myAppsBundle == NULL )	goto Bail;
	
	baseURL	= CFBundleCopyPrivateFrameworksURL( myAppsBundle );
	if ( baseURL == NULL )	goto Bail;

/*
	bundleURL = CFURLCreateCopyAppendingPathComponent( kCFAllocatorSystemDefault, baseURL, framework, false );
	if ( bundleURL == NULL )	goto Bail;
*/
	//replaces commented out section above.  This function now accepts a posix path to bundle.  
	bundleURL = CFURLCreateWithFileSystemPath (kCFAllocatorSystemDefault, framework, kCFURLPOSIXPathStyle, FALSE);
	if ( bundleURL == NULL )	goto Bail;

	*bundlePtr = CFBundleCreate( kCFAllocatorSystemDefault, bundleURL );
	if ( *bundlePtr == NULL )	goto Bail;

	if ( ! CFBundleLoadExecutable( *bundlePtr ) )
	{
		CFRelease( *bundlePtr );
		*bundlePtr	= NULL;
	}

Bail:															// Clean up.
	if ( bundleURL != NULL )	CFRelease( bundleURL );
	if ( baseURL != NULL )		CFRelease( baseURL );
}



PsychError StoreBitExitFunction(void)
{
	if(CocoaFreeBit != NULL)
		CocoaFreeBit();
		
	if(gStoreBitLibBundle!=NULL)
		CFBundleUnloadExecutable(gStoreBitLibBundle);
}