WIN: Movies, WaitBlanking, priority, and Rush

I'm relatively new to Psychtoolbox and have done some digging around
in the forum, but was wondering if anyone had a pre-written tutorial
on the following or is able to give a brief explanation:

I don't understand what goes on when I, for example, want to play a
movie while simultaneously monitoring for keyboard input and/or doing
calculations on data coming in from a data acquisition device. For
example, if I Rush a movie, e.g.

>>>
loop={
'for i=[1:101 101:-1:1];'
'Screen(window,''WaitBlanking'');'
'Screen(''CopyWindow'',w(i),window,rect,rect);'
'end;'
};
priorityLevel=MaxPriority(screenNumber,'WaitBlanking');
Rush(loop,priorityLevel);
>>>

does Matlab do anything during the intervals between screen refreshes?
Or does it just sit and wait each time I call WaitBlanking? Is this
true if I don't rush the movie?

What I'd really like to do is play a movie smoothly (i.e. not miss
frames), but be able to cut a movie short, move it to a different
location, and/or create/erase/move other items on the screen depending
on what the subject is doing while the movie runs.

I apologize for such a naive question, but I'd really love hearing
from someone who deals with this on a regular basis.

By the way, I'm using the most recent Psychtoolbox for Windows.

Thanks!
bschafer396@... asks:

> if I Rush a movie, e.g.
>
> >>>
> loop={
> 'for i=[1:101 101:-1:1];'
> 'Screen(window,''WaitBlanking'');'
> 'Screen(''CopyWindow'',w(i),window,rect,rect);'
> 'end;'
> };
> priorityLevel=MaxPriority(screenNumber,'WaitBlanking');
> Rush(loop,priorityLevel);
> >>>
>
> does Matlab do anything during the intervals between screen refreshes?
> Or does it just sit and wait each time I call WaitBlanking? Is this
> true if I don't rush the movie?

I haven't done exactly what you're doing, and I work on Macs, but I'm
pretty certain everything I'm about to write will be true for you too.
When Matlab reaches the call to 'WaitBlanking', it does just wait. If
you want something else to happen during each frame, you should put it
after the call to 'CopyWindow' or before the call to 'WaitBlanking'.
Whether or not you will get the behavior you want will depend, in
part, on your hardware. Probably also on the settings of your
monitor. You may need to work at lower frame rates so that looking
for keystrokes or mouse movements won't interfere with the timing of
your movie. Even then, it may not be possible to get exactly what you
want. You'll want to run some tests to find out what's possible.

Anyways, there are some things I had to struggle to discover, so
hopefully I can prevent you from going through the same struggles...
I have the following code in a function that is called inside a Rush
string. Wait, I take that back; it used to be inside a Rush string.
For my hardware I found a) that Rush-ing the code made no difference
timing wise, and b) sometimes caused the machine to hang. The latter
problem is almost certainly machine-specific. One of the things you
might want to test is whether or not Rush helps. Another is whether
or not moving the mouse interferes with your movie presentation in
ways that aren't visually obvious.

Anyways, my code (a major difference between what I did and what
you're doing is that I used lookup table modifications to generate my
movie; I've added some comments and removed some code you definitely
won't use to try to make this message more useful to you):

% Flicker is a structure that I use to hold on to a bunch of stimulus
% parameters. Flicker.RefreshRate is the FrameRate of the display,
% Flicker.Length is a time (in seconds) for how long the flickering
% should continue. If your movie is in a loop that you want to
% repeat but only for a pre-specified length of time, then you might
% use the same conditionals I've used

NumFlickerFrames = round(Flicker.RefreshRate*Flicker.Length);
Screen(window,'WaitBlanking',1);

t0 = GetSecs;

% As you'll figure out below, these are for timing checks
LoopCounter = 0;
WriteTimes = NaN*ones(NumFlickerFrames+2,1);

% Conditions for flicker: have not been flickering specified time,
% user has not destroyed the window that called this function
% and user has not entered any keys or mouse clicks signalling
% an end to the flickering [ those comments were already in
% my code -- you probably would put conditions like these
% inside your loop instead of as the outer call to 'while']

% in my code, these next three lines are all on one line; Yahoo
% wraps lines, so I break it up; Anyways, CallingFigh is a handle
% to the figure that contains the pushbutton uicontrol that the user
% clicked to start the movie, CallingBh is a handle to that
% pushbutton; I use that button as a means to centralize control of
% the movie; other controls have CallBacks that include a statement to
% set the UserData of CallingBh to 0. At the start of each loop,
% Matlab checks that UserData and will abort the loop if it is 0;
% Similarly, the intent of the "ismember" is to get Matlab to check to
% see that the user didn't use the mouse to close the controlling
% figure (which would destroy CallingBh and cause an error when Matlab
% tried to execute the "get")

while (GetSecs - t0 < Flicker.Length) & ...
ismember(CallingFigh,findobj('Type','figure')) & ...
get(CallingBh,'UserData')

% The next comments explain what took me quite a while to figure out;
% I *really* hope you find them useful...
% look for mouse clicks -- without the drawnow, mouse clicks
% will be functionally ignored. Without wrapping drawnow in
% EventAvail, moving the mouse around the screen
% causes the program to slow down

if EventAvail('mouseUp','mouseDown')
drawnow;
end;

% if you also want to check for keystrokes, you should put this
% (uncommented, of course) before the start of your loop:

%% Flush keyboard buffer
% while CharAvail
% GetChar;
% end
%
% See also: FlushEvents

% and this within your loop (probably right here after you've checked
% for mouse clicks):

% if CharAvail
% PressedKey = GetChar;
% switch PressedKey
% % Statements instructing program how to handle different keystrokes
% end
% end

% See also: KbCheck

% show next frame of clut movie
screen(window,'WaitBlanking',1);
st = GetSecs;

% This next line is where you would have your 'CopyWindow'
% statement
screen(window,'Gamma',theCluts(:,:,clutCounter),10);

% sp = GetSecs;

% My movie is nFrames long... And contained in a the 3-D
% matrix theCluts; that will only work for you if your movie
% has no spatial differences between frames. For instance, in
% my case the movie consists of one or two squares flickering
% in synchrony and never changing location
clutCounter=rem(clutCounter,nFrames)+1;
LoopCounter = LoopCounter+1;
% WriteTimes(LoopCounter) = sp-st;
end; % while showing movie

----------------

As I've recommended to others, you might want to set your timing
according to the number of frames instead of according to time. In my
case, that would mainly mean changing the first condition of the while
statement from "GetSecs - t0 < Flicker.Length" to "LoopCounter <
NumFlickerFrames". As I'm running my code now, I know how many loops there
should be, and I compare that to LoopCounter after the loop is
completed. At the moment I'm only using this code for physiology
experiments, so I can just discard data from any loops with improper
timing.

Hope this helps.

--
Mickey P. Rowe (mrowe@...)