function MovieDemo
% MovieDemo. Make and show a movie, easy as pie.
% 
% Also see DriftDemo, NoiseDemo, SpriteDemo, and ScreenTest.
% 
% ADVICE: If you want to show a big movie, you may be limited by the rate
% at which your computer can copy images from your offscreen window in
% computer memory to the onscreen window in the graphics card memory.
% (Such direct image copying is often called "blitting".) This
% "CopyWindow" rate is measured and reported by ScreenTest. Typical values
% for 2002 Macs and graphics cards range from 25 to 200 MB/s. Whether
% that's fast enough for your movie will depend on the pixel size (32-bit
% pixels take four times as long to copy as 8-bit pixels), what fraction
% of the screen you use, and what spatial (e.g. 640x480) and temporal
% resolution (e.g. 75 Hz) you select. E.g. Showing a full-screen 1152x768
% 60 Hz 8-bit pixel movie requires a CopyWindow rate of at least 
% 1x1152x768x60 Bytes/s = 51 MB/s.
% 
% CONSIDER USING SHOWTIME INSTEAD OF SCREEN:
% StŽphane Rainville <fanou101@hotmail.com> writes (7/02), "I was
% concerned with the fact that QuickTime attempts to respect a movie's
% frame rate irrespective of what the monitor's refresh might be. If movie
% and display frame rates don't match, QuickTime uses frame interpolation
% which could potentially mess up stimulus properties. Rather than
% relinquish control of the movie's timing properties to QuickTime, I
% proposed a simple two-punch work-around that uses 1 - ShowTime's ability
% to display any single frame of a QT movie, and 2 - the PsychToolbox's
% well established ability to sync images with the monitor's vertical
% refresh. The heart of the code looks something like
% 	for frame=1:n
% 	  ShowTime('MovieFrameDisplay',movie,frame);
% 	  framesSinceLastWait=SCREEN(window,'WaitBlanking');
% 	end
% "Visually, this seems to work well and is confirmed by
% framesSinceLastWait which never missed a beat during my tests. If the
% 'WaitBlanking' is commented out of the program, the QT movie misses all
% vertical refresh interrupts and screams by in a fraction of second,
% horizontal tear and all. I also did a SCREEN('GetImage') on each frame
% of the movie and that confirmed that movie presentation is lossless
% (i.e. no key frame interpolation). Bottom line, at least for my
% purposes, Showtime seems to be robust both spatially and temporally. The
% main advantage for me at the moment is that QuickTime movies come in a
% single file and load much more quickly than loading an array of
% individual frames stored in separate image files (e.g. TIF)."
% 
% p.s. We've read that QuickTime has polished code for blitting (copying
% quickly to the screen) that may beat QuickDraw's CopyBits, which is what
% Screen 'CopyWindow' uses. This may constitute another advantage of using
% StŽphane's approach to showing movies. It would be interesting to pit
% QuickTime against QuickDraw in this way, ie ShowTime 'MovieFrameDisplay'
% vs Screen 'CopyWindow', and compare their data transfer rates in MB/s.

% 1/97  	dgp  Wrote it.
% 2/24/97	dhb  Added comments, cosmetic editing.
% 3/15/97	dgp  Hide cursor.
% 4/2/97  dhb  Change -1 to 255 in call to FillOval.
% 4/15/97 dgp  Open window first. Specify which screen explicitly.
% 5/31/97 dgp  Add Rush.
% 6/1/97 	dgp  Make variable names less cryptic.
% 8/9/97  dhb  Explicitly set pixel size.
% 8/21/97	dhb	 Make printout less ominous, make note in comment.
% 2/1/98	dgp	 Use MaxPriority in call to Rush.
% 2/2/98	dgp	 Move the movie down to middle of screen, to avoid tearing.
% 7/21/98	dgp	 Added reminder to make sure all Rushed functions are in memory.
% 9/30/99	dgp	 Removed 'CopyBitsQuickly' argument from first call to CopyWindow.
% 12/10/01  awi  Conditionally execute Rush only on Mac. 
% 2/21/02   dgp  Print the priority.
% 03/01/02  awi Restored Rush to Windows version. 
%               Removed Rect args to 'CopyWindow' in loop because of a bug in Win version of Screen 'CopyWindow'.
%               Merged together Mac and Windows versions which had fallen out of sync.
% 4/13/02	awi	Could restore Rect Args to 'CopyWindow' but saw no need.  Earlier assessment of a bug in the Win version 
%							of Screen 'CopyWindow' was bogus. The problem is really that, under Windows, the offscreen windows are 
%							the size of the Onscreen window, slowing down the copy operation.    
% 			awi Fixed small bug where the yet-undeclared variable "priorityLevel" was printed before the first loop.
% 4/14/02   awi -The offscreen windows on Windows are now the size specified by the value of variable "rect", not the size of
%               the full-screen onscreen window.   This fixes the problem noted on 4/13/02 with slow copying between offscreen 
%               and onscreen Windows windows.  Moved the onscreen movie window to the upper left corner of the screen for  
%               similiar appearance on Mac and Windows without platform conditionals.
%               -Added 'WaitSecs' call to give Windows time to display its onscreen window.   
%               -Removed superfluous call to Screen 'Rect' fetching the size of the offscreen window rect, which we already know.  
%               -Checked to make sure that "MovieDemo.m is only 35 lines..." is still accurate.  
% 4/15/02 dgp Use full screen window. Show movie at lower right, so the ball bounces off the walls.
% 6/20/02 dgp Added timing and ADVICE.
% 6/20/02 awi Also see SpriteDemo.  

fprintf('MovieDemo.m is only 50 lines, plus comments. Read it to see how easy it \nis to show movies.\n\n');

% Open a window
screenNumber=0;
pixelSize=8;
[window,windowRect]=Screen(screenNumber,'OpenWindow',[],[],pixelSize);
n=300;
% n=min(windowRect(RectBottom),2*round((Bytes*2-1e6)^0.33/2)); % make movie as big as memory will allow.
rect=[0 0 n n];
rect2=AlignRect(rect,windowRect,RectRight,RectBottom);

waitSecs(1); % Give display a moment to recover from the change of pixelSize

% Make a movie by drawing disks into 1+n/2 offscreen windows.
black=BlackIndex(window);
for i=1:(1+n/2)
	w(i)=Screen(window,'OpenOffscreenWindow',[],rect);
	w(n+2-i)=w(i);
	r=[0 0 2 2]*(i-1);
	Screen(w(i),'FillOval',black,r);
end

% Show the movie, first forwards, then backwards.
Screen(window,'TextSize',24);
Screen(window,'DrawText','Showing movie at priority 0 ...',10,30);
HideCursor;
for i=1:length(w)
	Screen(window,'WaitBlanking');
	s(i)=GetSecs;
	Screen('CopyWindow',w(i),window,rect,rect2);
end
s=diff(s);
frames1=sum(s)*FrameRate(screenNumber)-length(s);

% Show the movie again, now using Rush to minimize interruptions.
loop={
'for i=1:length(w);'
'Screen(window,''WaitBlanking'');'
's(i)=GetSecs;'
'Screen(''CopyWindow'',w(i),window,rect,rect2);'
'end;'
};
priorityLevel=MaxPriority(screenNumber,'WaitBlanking');
Screen(window,'FillRect');
Screen(window,'DrawText',sprintf('Showing movie at priority %g ...\n',priorityLevel),10,30);
i=0;Screen('Screens'); % Make sure all Rushed variables and functions are in memory.
Rush(loop,priorityLevel);
s=diff(s);
frames2=sum(s)*FrameRate(screenNumber)-length(s);
ShowCursor;

% Close the on- and off-screen windows
Screen('CloseAll');

if round(frames1)==0 & round(frames2)==0
	s=sprintf('Success! The movie was shown twice. Both showings were frame-accurate.');
else
	s=sprintf('The movie was shown twice, running over by %.0f frames in the first and %.0f frames in the second showing.',frames1,frames2);
end
s=sprintf('%s The first showing may have been jerky, due to interruptions. The second showing used Rush, at priority %g, to minimize interruptions, to make the movie run smoothly. See MovieTearDemo and Rush.',s,priorityLevel);
fprintf('%s\n',WrapString(s));
