/usr/share/psychtoolbox-3/PsychBasic/KbQueueWait.m is in psychtoolbox-3-common 3.0.14.20170103+git6-g605ff5c.dfsg1-1build1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 | function secs=KbQueueWait(deviceIndex, forWhat, untilTime)
% secs=KbQueueWait([deviceIndex][, forWhat=0][, untilTime=inf])
%
% Waits for any key to be pressed and returns the time of the press. The
% optional 'forWhat' parameter controls what kind of event is waited for
% (similar to KbWait).
% forWhat:
% 0: return as soon as a key is down
% 1: return as soon as no keys are down
% 2: wait for a key press (so if a key is already down upon function
% entering, it is ignored):
% waitForAllKeysReleased -> waitForKeypress
% 3: wait for a keystroke like, 2, but wait until key is released after
% pressing it:
% waitForAllKeysReleased -> waitForKeypress -> waitForAllKeysReleased
%
% If the optional parameter 'untilTime' is provided, KbWait will only wait
% until that time and then return regardless if anything happened on the
% keyboard or not.
%
% KbQueueFlush should not be called immediately prior to this function. If
% you do that and clear prior events, KbQueueWait is not able to determine
% whether a key is down or not upon function entry (important for all four
% forWhat modes). It will assume no keys are down and, e.g., return
% immediate when forWhat is 1 even though a key was depressed before the
% flush and is still being held. KbQueueWait correctly deals with previous
% events in the buffer.
% NB. Previously, use of KbQueueFlush before calling this function was
% recommended. The current function maintains backwards compatibility for
% this use case. However, any changes of existing code to follow the new
% recommendation and remove preceding KbQueueFlush calls should be
% carefully considered and tested (don't change what works).
%
% Note that this command will not respond to any keys that were inactivated
% by using the keyList argument to KbQueueCreate.
%
% Since KbQueueWait is implemented as a looping call to KbQueueCheck, it
% will not respond to any key codes stored in the global variable
% ptb_kbcheck_disabledKeys (see "help DisableKeysForKbCheck")
% _________________________________________________________________________
%
% See also: KbQueueCreate, KbQueueStart, KbQueueStop, KbQueueCheck,
% KbQueueWait, KbQueueFlush, KbQueueRelease
% 8/19/07 rpw Wrote it.
% 8/23/07 rpw Modifications to add KbQueueFlush
% 5/14/12 mk Small fixes: Use 1 msec wait interval.
% 7/29/16 dcn Added forWhat and untilTime arguments mirroring KbWait
% 8/31/16 dcn Additional help note about changed KbQueueFlush
% recommendation
if nargin < 1
deviceIndex = [];
end
% Try to check if keyboard queue for 'deviceIndex' is reserved for our exclusive use:
if ~KbQueueReserve(3, 2, deviceIndex) && KbQueueReserve(3, 1, deviceIndex)
if isempty(deviceIndex)
deviceIndex = NaN;
end
error('Keyboard queue for device %i already in use by GetChar() et al. Use of GetChar and keyboard queues is mutually exclusive!', deviceIndex);
end
% It is implicit in invoking this function that the queue should be running
% and it is potentially problematic if it is not since the function will
% never return, therefore, go ahead and start the queue if it isn't running
KbQueueStart(deviceIndex);
if nargin < 2 || isempty(forWhat)
forWhat = 0;
end
if nargin < 3 || isempty(untilTime)
untilTime = inf;
end
% Wait for keystroke?
if forWhat >= 2
% Wait for keystroke, ie., first make sure all keys are released, then
% wait for a keypress:
% Wait until all keys are released
KbQueueWaitInternal(deviceIndex, 1, untilTime, true);
if forWhat == 2
% Now just go on with forWhat = 0, i.e., wait for keypress:
secs = KbQueueWaitInternal(deviceIndex, 0, untilTime, false);
else
% Wait for keypress (we want time of the press, not the later
% release):
secs = KbQueueWaitInternal(deviceIndex, 0, untilTime, false);
% Wait for key release.
KbQueueWaitInternal(deviceIndex, 1, untilTime, false);
end
else
secs = KbQueueWaitInternal(deviceIndex, forWhat, untilTime, true);
end
% helper function that provides some extra control to implement higher
% forWhats correctly
function secs = KbQueueWaitInternal(deviceIndex, forWhat, untilTime, qFirst)
secs = -inf;
while secs < untilTime
[~,~,~,p,r] = KbQueueCheck(deviceIndex);
if ~forWhat && any(p>r) % waiting for key down
% if for any key, last down was later than last up, it is currently
% down
secs=min(p(p>r));
return;
elseif forWhat && any(r>p) % waiting for key up
% if for none of the keys last down was later than last up, no keys
% are currently down. also nothing down if all fields are 0
secs=max(r(r>p));
return;
elseif qFirst
% special case for first iteration: if no key event in buffer at
% all, we'll have to assume all keys are up. if waiting for keys
% up, return now
if forWhat && ~any(p) && ~any(r)
return;
end
qFirst = false;
end
% Wait for 1 msec to prevent system overload:
secs = WaitSecs('Yieldsecs', 0.001);
end
|