PageRenderTime 59ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/Expectator/emoLabel (Video Annotation)/myplay.m

http://siento.googlecode.com/
MATLAB | 1683 lines | 1001 code | 220 blank | 462 comment | 142 complexity | 191dfdb768e78322078a3fe8d2e2f7b1 MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0
  1. function mov = myplay(varargin)
  2. %MPLAY Play a movie interactively.
  3. % MPLAY(A) opens a new movie player GUI and loads movie data
  4. % A into the player. Multiple players may be used at one time.
  5. %
  6. % MPLAY(A, FMT) explicity specifies a format string FMT for the
  7. % movie data, in case a warning from MPLAY(A) indicates ambiguity
  8. % in interpreting the format of A.
  9. %
  10. % MPLAY(A, FPS) or MPLAY(A, FMT, FPS) specifies the default
  11. % frame rate, FPS, for the movie, in frames per second. If
  12. % omitted, FPS defaults to 30. The GUI supports interactive
  13. % changes to FPS as well.
  14. %
  15. % M=MPLAY(...) returns a MoviePlayerAPI object, M, useful for
  16. % programmatic control of the movie player GUI. A list of
  17. % all available object methods is obtained from "methods(M)".
  18. %
  19. % Movie formats
  20. % -------------
  21. % Movie A may be one of the following formats:
  22. %
  23. % Standard MATLAB movie structure (FMT = 'structure' or 'S')
  24. % See 'help getframe' for more information on the MATLAB
  25. % movie structure. Only movies with empty .colormap field
  26. % entries are supported.
  27. %
  28. % Intensity video array (FMT = 'intensity' or 'I')
  29. % 3-D array organized as MxNxF, where each image is of size
  30. % MxN and there are F image frames. An input with size
  31. % exactly MxNx3 will be interpreted as a 3-frame intensity movie.
  32. %
  33. % RGB video array (FMT = 'RGB')
  34. % 4-D array organized as MxNx3xF, where the R, G, and B
  35. % are encoded in the 3rd dimension. Note that MxNx3 is
  36. % the usual MATLAB format for an RGB image.
  37. %
  38. % Video frame data type may be double, uint8, or uint16.
  39. %
  40. % Keyboard support
  41. % ----------------
  42. % P:Play F:FFwd Rt:StepFwd Up:First J:Jump X:FwdBkwd
  43. % S:Stop R:Rew Lt:StepRev Dn:Last L:Loop
  44. %
  45. % EXAMPLE: Playback of standard MATLAB movies.
  46. % Run 'crulspin' or 'logospin' from the command line.
  47. % These demos create a MATLAB movie structure in the
  48. % workspace in variable 'm'. Run "mplay(m)" and be
  49. % sure to turn on looping playback.
  50. %
  51. % See also MOVIE, INT2RGBM, INT2STRUCT, STRUCT2RGBM, IMVIEW.
  52. % Copyright 2003 The MathWorks, Inc.
  53. % Author: D. Orofino
  54. % $Revision: $ $Date: $
  55. % To do:
  56. % ------
  57. % - icon for export-to-imview
  58. % - API properties: colormap
  59. % - Interactive zoom
  60. % Note: The following input syntax has been disabled in the
  61. % CheckMovieFormat() function.
  62. %
  63. % Color video components (FMT = @user_fcn)
  64. % Cell array containing arrays reprsenting each color plane of a movie,
  65. % arranged in a form suitable for a pre-defined conversion function.
  66. % In this case, FMT specifies a function (string or function handle) that
  67. % converts from the color components to the 4-D RGB video format. The
  68. % function is invoked as: RGBM = user_fcn(A{:}). The function must
  69. % return a 4-D RGB movie array. If omitted, FMT defaults to @int2rgbm.
  70. %
  71. % Examples:
  72. % MPLAY({R,G,B},@int2rgbm) % converts RGB components to 4-D array
  73. % MPLAY({R,G,B},10) % uses int2rgbm by format, 10 frames/sec
  74. % MPLAY({Y,U,V},@yuv2rgbm,24) % 24 frames/sec, YUV data format
  75. %
  76. % GUI Data organization
  77. % ---------------------
  78. % Figure UserData
  79. % .hfig handle to figure window
  80. % .haxis handle to axis containing image object
  81. % .himage handle to image object
  82. % .htoolbar handle to GUI button toolbar
  83. % .htimer timer object associated with this player
  84. % .hStatusBar structure of handles to parts of status bar
  85. % .loopmode 0=no looping, 1=looping
  86. % .fbmode 0=no fwd/bkwd playback, 1=fwd/bkwd playback
  87. % .fbrev 1=currently in reverse-playback, only if fwd/bkwd flag true
  88. % .paused true/false flag indicating that we're in
  89. % pause mode --- set to false by pressing play or stop
  90. % .nextframe next frame number to display
  91. % .currframe current frame displayed in viewer
  92. % .jumpto_frame frame number to jump to for frame num edit
  93. % .fps requested frame rate (frames per second)
  94. % .varName name of variable passed in to player
  95. % .numFrames number of frames in movie
  96. % .frameRows number of rows in movie image
  97. % .frameCols number of columns in movie image
  98. % .cmapexpr colormap expr to use during movie playback
  99. % .cmap
  100. % .UpdateImageFcn function pointer to image update fcn
  101. % .Movie movie pixel data
  102. % .MovieFormat 'S' Standard movie structure
  103. % 'I' MxNxF
  104. % 'RGB' MxNx3xF
  105. %
  106. % Timer Object UserData
  107. % .hfig handle to corresponding figure window
  108. try,
  109. % dfmt: desired movie format, as specified by user
  110. [A,dfmt,fps,msg] = parse_inputs(varargin{:});
  111. error(msg);
  112. % fmt: actual movie format to use,
  113. % string normalized to proper spelling, capitalization, etc
  114. [A, fmt] = CheckMovieFormat(A, dfmt);
  115. % Create and load GUI with movie
  116. hfig = CreateGUI;
  117. LoadMovie(hfig, A, fmt, inputname(1), fps);
  118. UpdateGUIControls(hfig);
  119. AdjustPlayerSize(hfig);
  120. % Return object is LHS requested
  121. if nargout>0, mov=GetMoviePlayerAPI(hfig); end
  122. % Clean up
  123. set(hfig,'vis','on'); % time to show the player
  124. catch,
  125. rethrow(lasterror);
  126. end
  127. % --------------------------------------------------------
  128. function AdjustPlayerSize(hfig)
  129. % Adjust width of player window to be no narrower than
  130. % the extent needed to render the button and status bar
  131. %
  132. % Also, make sure it is no bigger than screen size
  133. min_width = 370; % min pixel width to render toolbar
  134. set(hfig,'units','pix');
  135. figpos = get(hfig,'pos');
  136. % Widen player to minimum width (if movie is very narrow)
  137. if figpos(3) < min_width,
  138. figpos(3) = min_width;
  139. end
  140. % Shrink movie to screen as needed:
  141. set(0,'units','pix');
  142. screenpos = get(0,'screensize');
  143. if figpos(3) > screenpos(3),
  144. figpos(3) = screenpos(3);
  145. end
  146. if figpos(4) > screenpos(4),
  147. figpos(4) = screenpos(4);
  148. end
  149. set(hfig,'pos',figpos);
  150. % --------------------------------------------------------
  151. function mov = GetMoviePlayerAPI(hfig)
  152. fcn.ffwd = @cb_ffwd;
  153. fcn.goto_end = @cb_goto_end;
  154. fcn.goto_start = @cb_goto_start;
  155. fcn.jumpto = @cb_jumpto;
  156. fcn.loop = @cb_loop;
  157. fcn.fbmode = @cb_fbmode;
  158. fcn.play = @cb_play;
  159. fcn.rewind = @cb_rewind;
  160. fcn.step_back = @cb_step_back;
  161. fcn.step_fwd = @cb_step_fwd;
  162. fcn.stop = @cb_stop;
  163. fcn.truesize = @cb_truesize;
  164. fcn.setfps = @ext_setFPS;
  165. fcn.getfps = @ext_getFPS;
  166. mov = mmovie.player(hfig,fcn);
  167. % --------------------------------------------------------
  168. function [A,fmt,fps,msg] = parse_inputs(varargin)
  169. %PARSE_INPUTS Parse input arguments
  170. % Valid calling syntax:
  171. % MPLAY(A)
  172. % MPLAY(A, FMT)
  173. % MPLAY(A, FPS)
  174. % MPLAY(A, FMT, FPS)
  175. %
  176. % Defaults:
  177. A=[];
  178. fmt=''; % no format specified
  179. fps=30; % 30 frames per second
  180. msg=''; % no errors
  181. % Check number of input args
  182. msg = nargchk(1,3,nargin);
  183. if ~isempty(msg), return; end
  184. A = varargin{1};
  185. if nargin > 2,
  186. % 3 or more inputs
  187. fmt = varargin{2};
  188. fps = varargin{3};
  189. elseif nargin==2
  190. % 2 inputs
  191. if ischar(varargin{2}),
  192. fmt = varargin{2};
  193. else
  194. % must disambiguate:
  195. % (A,@my_func) from (A,fps)
  196. if isnumeric(varargin{2}),
  197. fps = varargin{2};
  198. else
  199. fmt = varargin{2};
  200. end
  201. end
  202. end
  203. % Check and expand FMT
  204. % Expand the desired format string specified by user
  205. % Make it lower case, and complete any partial string specified.
  206. %
  207. % NOTE: If A is a cell-array, skip this
  208. % FMT could be a conversion function
  209. %
  210. if ~iscell(A),
  211. if ~isempty(fmt),
  212. if ~ischar(fmt),
  213. msg = 'FMT must be a string.';
  214. return
  215. end
  216. all_in={'intensity','rgb','structure'}; % user format strings
  217. all_out={'I','RGB','S'}; % internal format strings
  218. i=strmatch(lower(fmt), all_in);
  219. if isempty(i),
  220. msg='Unrecognized FMT string specified.';
  221. return
  222. end
  223. fmt=all_out{i};
  224. end
  225. end
  226. % Check FPS
  227. if ~isa(fps,'double') || numel(fps)~=1 || fps<=0,
  228. msg='FPS must be a scalar double-precision value > 0.';
  229. return
  230. end
  231. % --------------------------------------------------------
  232. function [A,fmt,msg] = CheckMovieFormat(A,dfmt)
  233. % DetermineMovieFormat
  234. % Rules to disambiguate inputs when no format is specified
  235. %
  236. % Is input a structure?
  237. % - 'struct' assumed
  238. % check for .colormap and .cdata present
  239. % check for empty .colormap entries
  240. % check for MxN or MxNx3 sizes in each frame
  241. % - otherwise, ERROR
  242. %
  243. % Is input numeric?
  244. % - if not, ERROR
  245. %
  246. % Is input 4-D?
  247. % Are both the 1st and 3rd dims ~= 3 (or empty)?
  248. % ERROR
  249. % Are both the 1st and 3rd dims == 3?
  250. % - assume 'rgb'
  251. % - WARN user of ambiguity, and to pass 'rgb' format string
  252. % to suppress warning next time
  253. % Is the 1st dim = 3 and the 3rd dim ~= 3?
  254. % - 'rgbp' assumed
  255. % Is the 1st dim ~= 3 and the 3rd dim = 3?
  256. % - 'rgb' assumed
  257. %
  258. % Is input 3-D?
  259. % Is the 3rd dim = 3?
  260. % WARN that this is being interpreted as a 3-frame intensity movie,
  261. % and to pass 'intensity' format string to suppress warning next time
  262. %
  263. % Is input 2-D?
  264. % - 'intensity' assumed, one frame
  265. %
  266. % Otherwise, ERROR
  267. fmt = ''; % default
  268. CR = sprintf('\n');
  269. % Check for movie structure format
  270. %
  271. if isstruct(A),
  272. fmt = 'S';
  273. if ~isempty(dfmt) && ~strcmp(fmt,dfmt),
  274. error('Movie format (%s) doesn''t match specified format (%s)',fmt,dfmt);
  275. end
  276. % Check for required fields
  277. if ~isfield(A, 'colormap') || ~isfield(A, 'cdata'),
  278. error('Invalid movie: structure format does not contain required fields.');
  279. end
  280. % Check for empty colormap fields and movie datatypes
  281. % - check all frames (thorough but time consuming)
  282. % - check just the first frame (quick but incomplete)
  283. %
  284. i=1; % just check first frame
  285. %for i=1:length(A), % check all entries in structure
  286. if ~isempty(A(i).colormap),
  287. error('All colormap fields in structure format must be empty.');
  288. end
  289. c=class(A(i).cdata);
  290. switch c,
  291. case {'uint8','double'},
  292. otherwise,
  293. error('Unsupported data type (%s) found in video frames.', c);
  294. end
  295. %end
  296. return
  297. end
  298. % Check for cell-array arguments
  299. %
  300. % NOTE: Disabled color conversion syntax
  301. if 0,
  302. if iscell(A),
  303. % Convert cell array of color components to 4-D RGB video array
  304. % using user-defined conversion function
  305. % Default if no conversion function specified: int2rgbm
  306. if isempty(dfmt),
  307. fmt = @int2rgbm;
  308. else
  309. fmt = dfmt;
  310. end
  311. % Try to invoke conversion function
  312. A = feval(fmt, A{:});
  313. % After the conversion, it is assumed that the video format is RGB
  314. fmt = 'RGB';
  315. dfmt = 'RGB';
  316. % Fall-through to standard checking-code for N-D array
  317. % after conversion function has completed
  318. end
  319. end
  320. if ~isnumeric(A),
  321. error('Unrecognized movie format.');
  322. end
  323. % Check for 3-D and 4-D RGB array formats
  324. %
  325. nd = ndims(A);
  326. sz = size(A);
  327. if nd==4,
  328. A33 = (sz(3)==3);
  329. if ~A33,
  330. error('Invalid movie format: 3rd dimension of array must be 3.');
  331. end
  332. fmt = 'RGB';
  333. if ~isempty(dfmt) && ~strcmp(fmt,dfmt),
  334. error('Movie format (%s) doesn''t match specified format (%s)',fmt,dfmt);
  335. end
  336. return
  337. elseif nd==3,
  338. A33 = (sz(3)==3);
  339. if A33 && isempty(dfmt),
  340. warning(['Ambiguous movie format: 3rd dimension of 3-D array is 3.' CR ...
  341. 'Assuming ''intensity'' format. Pass format string to suppress warning.']);
  342. end
  343. fmt='I';
  344. if ~isempty(dfmt) && ~strcmp(fmt,dfmt),
  345. error('Movie format (%s) doesn''t match specified format (%s)',fmt,dfmt);
  346. end
  347. return
  348. else % 2-D input
  349. fmt='I';
  350. if ~isempty(dfmt) && ~strcmp(fmt,dfmt),
  351. error('Movie format (%s) doesn''t match specified format (%s)',fmt,dfmt);
  352. end
  353. return
  354. end
  355. % --------------------------------------------------------
  356. function hfig = CreateGUI
  357. % Determine renderer mode
  358. if 0 & opengl('info'),
  359. renderer='opengl';
  360. else
  361. renderer='painters';
  362. end
  363. % Create figure
  364. defaultPos = [50 50 400 400];
  365. hfig = figure(...
  366. 'NumberTitle','off', ...
  367. 'MenuBar','none', ...
  368. 'Renderer',renderer, ...
  369. 'HandleVis','callback', ...
  370. 'IntegerHandle','off', ...
  371. 'KeyPressFcn', @KeypressFcn, ...
  372. 'Visible','off', ...
  373. 'CloseRequestFcn',@DeleteFcn, ...
  374. 'DeleteFcn',@DeleteFcn, ...
  375. 'Position',defaultPos, ...
  376. 'BackingStore','off', ...
  377. 'DoubleBuffer','off');
  378. % Setup movie area
  379. defaultN = 64;
  380. haxis = axes( ...
  381. 'parent',hfig, ...
  382. 'pos',[0 0 1 1], ...
  383. 'vis','off', ...
  384. 'xlim',[1 defaultN], ...
  385. 'ylim', [1 defaultN], ...
  386. 'ydir','reverse', ...
  387. 'xlimmode','manual',...
  388. 'ylimmode','manual',...
  389. 'zlimmode','manual',...
  390. 'climmode','manual',...
  391. 'alimmode','manual',...
  392. 'layer','bottom',...
  393. 'nextplot','add', ...
  394. 'dataaspectratio',[1 1 1], ...
  395. 'drawmode','fast');
  396. himage = image(...
  397. 'parent',haxis, ...
  398. 'cdata',zeros(defaultN), ...
  399. 'xdata',1:defaultN, ...
  400. 'ydata',1:defaultN, ...
  401. 'erase','none');
  402. % Setup default figure data
  403. %
  404. ud = get(hfig,'userdata');
  405. ud.hfig = hfig;
  406. ud.haxis = haxis;
  407. ud.himage = himage;
  408. ud.htoolbar = CreateButtonBar(hfig);
  409. ud.htimer = [];
  410. ud.hStatusBar = AddStatusBar(hfig);
  411. ud.loopmode = 0; % non-looping
  412. ud.fbmode = 0; % no fwd/bkwd playback
  413. ud.fbrev = 0; % not in rev-playback
  414. ud.paused = 0;
  415. ud.nextframe = 1;
  416. ud.currframe = 0;
  417. ud.jumpto_frame = 1;
  418. ud.fps = 0; % frames per second
  419. ud.varName = ''; % variable name passed to player
  420. ud.numFrames = 0;
  421. ud.frameRows = 0;
  422. ud.frameCols = 0;
  423. ud.cmapexpr = 'gray(256)'; % default
  424. ud.cmap = gray(256); % default
  425. ud.UpdateImageFcn = [];
  426. ud.Movie = [];
  427. ud.MovieFormat = '';
  428. set(hfig,'userdata', ud);
  429. % Finishing touches:
  430. % - show GUI
  431. % - enable resize fcn
  432. set(hfig, ...
  433. 'colormap', ud.cmap, ...
  434. 'resizefcn', @ResizeFcn);
  435. % -------------------------------------------------------------------------
  436. function KeypressFcn(hcb, eventStruct)
  437. % Handle keypresses in main window
  438. hfig = gcbf;
  439. key = get(hfig, 'CurrentChar');
  440. if ~isempty(key), % unix keyboard has an empty key
  441. switch lower(key)
  442. case char(29) % right
  443. cb_step_fwd(hfig,[]);
  444. case char(28) % left
  445. cb_step_back(hfig,[]);
  446. case 'f'
  447. cb_ffwd(hfig,[]);
  448. case 'r'
  449. cb_rewind(hfig,[]);
  450. case 's'
  451. cb_stop(hfig,[]);
  452. case 'p'
  453. cb_play(hfig,[]); % play/pause
  454. case char(30) % up
  455. cb_goto_start(hfig,[]);
  456. case char(31) % down
  457. cb_goto_end(hfig,[]);
  458. case 'j' % jump to
  459. EditFrameNum(hfig);
  460. case 'l' % loop
  461. cb_loop(hfig,[]);
  462. case 'x' % fwd/bkwd playback
  463. cb_fbmode(hfig,[]);
  464. case char(13) % Enter
  465. % Open parameters dialog
  466. EditProperties(hfig);
  467. end
  468. end
  469. % --------------------------------------------------------
  470. function DeleteFcn(hcb, eventStruct)
  471. % How to get here:
  472. % Close all force
  473. % delete(h)
  474. hfig=gcbf;
  475. ud = get(hfig,'userdata');
  476. if ~isempty(ud),
  477. stop(ud.htimer); % Shut off timer if running
  478. end
  479. delete(hfig); % Close window
  480. % --------------------------------------------------------
  481. function ResizeFcn(hcb, eventStruct)
  482. fd = get(hcb,'UserData'); % hcb = hfig
  483. hAll = fd.hStatusBar.All;
  484. % Get positions and compute resize offsets:
  485. fig_pos = get(hcb,'pos');
  486. frame_pos = get(fd.hStatusBar.Region,'pos');
  487. frame_rt = frame_pos(1)+frame_pos(3)-2;
  488. delta = fig_pos(3)-frame_rt;
  489. % Adjust positions:
  490. for i=1:length(hAll),
  491. pos = get(hAll(i),'pos');
  492. pos(1) = pos(1) + delta;
  493. set(hAll(i),'pos',pos);
  494. end
  495. % Separately adjust hStatusBar.Region
  496. % Grow it wider, don't move it:
  497. pos = frame_pos;
  498. pos(3)=pos(3)+delta;
  499. set(fd.hStatusBar.Region,'pos',pos);
  500. % --------------------------------------------------------
  501. function hStatusBar = AddStatusBar(hfig)
  502. hfig_pos = get(hfig,'pos');
  503. CR = sprintf('\n');
  504. % Status region frame
  505. bg = [1 1 1]*.8;
  506. pos=[0 0 hfig_pos(3)+2 22];
  507. hStatusBar.Region = uicontrol('parent',hfig, ...
  508. 'style','frame', ...
  509. 'units','pix', ...
  510. 'pos',pos, ...
  511. 'backgr', bg, ...
  512. 'foregr', [1 1 1]);
  513. % Render right after background frame, so when resizing occurs,
  514. % this will be "overwritten" by other data
  515. hStatusBar.StatusText = uicontrol('parent',hfig, ...
  516. 'style','text', ...
  517. 'units','pix', ...
  518. 'pos',[2 1 100 16], ...
  519. 'string','Ready', ...
  520. 'horiz','left', ...
  521. 'backgr',bg, ...
  522. 'foregr','k');
  523. % Indents for display/trace timing
  524. pos1 = [pos(3)-64 1 60 17];
  525. [hStatusBar.FPS, hAll1] = makeStatusBarIndent(hfig,bg,pos1);
  526. set(hStatusBar.FPS,'string','FPS: 0', ...
  527. 'tooltip' ,['Frames Per Second']);
  528. set(hAll1,'ButtonDownFcn',@cb_properties);
  529. pos2 = [pos(3)-128 1 60 17];
  530. [hStatusBar.FrameNum, hAll2] = makeStatusBarIndent(hfig,bg,pos2);
  531. set(hStatusBar.FrameNum,'string','0:0', ...
  532. 'tooltip', ['Current Frame : Total Frames']);
  533. set(hAll2,'ButtonDownFcn',@cb_jumpto);
  534. pos2 = [pos(3)-148-74 1 90 17];
  535. [hStatusBar.FrameSize, hAll3] = makeStatusBarIndent(hfig,bg,pos2);
  536. set(hStatusBar.FrameSize,'string','(FrameSize)', ...
  537. 'tooltip', '(framesize readout)');
  538. % set(hAll3,'ButtonDownFcn',@cb_properties);
  539. % Group all status bar widget handles together, for resizing:
  540. hStatusBar.All = [hAll1 hAll2 hAll3];
  541. % -------------------------------------------------------------------------
  542. function [h, hall] = makeStatusBarIndent(hfig,bg,pos1)
  543. hall(1)=uicontrol('parent',hfig, ...
  544. 'style','frame', ...
  545. 'units','pix', ...
  546. 'pos',pos1, ...
  547. 'backgr', bg, ...
  548. 'foregr', [1 1 1]*.4);
  549. pos2=pos1;
  550. pos2(4)=1;
  551. hall(2)=uicontrol('parent',hfig, ...
  552. 'style','frame', ...
  553. 'units','pix', ...
  554. 'pos',pos2, ...
  555. 'backgr', [1 1 1], ...
  556. 'foregr', [1 1 1]);
  557. pos2=[pos1(1)+pos1(3)-1 pos1(2) 1 pos1(4)];
  558. hall(3)=uicontrol('parent',hfig, ...
  559. 'style','frame', ...
  560. 'units','pix', ...
  561. 'pos',pos2, ...
  562. 'backgr', [1 1 1], ...
  563. 'foregr', [1 1 1]);
  564. hall(4) = uicontrol('parent',hfig, ...
  565. 'style','text', ...
  566. 'units','pix', ...
  567. 'horiz','left', ...
  568. 'fontweight','light', ...
  569. 'fontsize',8, ...
  570. 'pos',pos1+[2 2 -3 -3], ...
  571. 'string', 'test', ...
  572. 'backgr', bg, ...
  573. 'foregr', [0 0 0]);
  574. h=hall(4); % main text widget
  575. % -------------------------------------------------------------------------
  576. function UpdateStandardStatusText(hfig)
  577. % Setup some status bar text, indicating
  578. % current scope state
  579. %
  580. ud = get(hfig,'userdata');
  581. isRunning = strcmp(get(ud.htimer,'Running'),'on');
  582. isPaused = ~isRunning & ud.paused;
  583. isStopped = ~isRunning & ~ud.paused;
  584. if isStopped, str = 'Stopped';
  585. elseif isPaused, str = 'Paused';
  586. else str = 'Playing';
  587. end
  588. UpdateStatusText(hfig,str);
  589. % -------------------------------------------------------------------------
  590. function UpdateStatusText(hfig,str)
  591. % Set arbitrary text into status region
  592. if isempty(hfig), return; end
  593. fd = get(hfig,'UserData');
  594. set(fd.hStatusBar.StatusText,'string',str);
  595. % --------------------------------------------------------
  596. function UpdateGUIControls(hfig)
  597. % Update GUI state, including:
  598. % - button enable states/icons
  599. % - status bar text
  600. UpdateButtonEnables(hfig);
  601. UpdateStandardStatusText(hfig);
  602. % --------------------------------------------------------
  603. function UpdateButtonEnables(hfig)
  604. % Button states:
  605. % Enabled=1
  606. % Disabled=0
  607. % stopped paused running
  608. % Props (all 1)
  609. % Truesz (all 1)
  610. % Export (all 1)
  611. %
  612. % 1st (all 1)
  613. % Rew (all 1)
  614. % StepRev 1 1 0
  615. % Stop 0 1 1
  616. % Play 1 1 1
  617. % StepFwd 1 1 0
  618. % FFwd (all 1)
  619. % Last (all 1)
  620. %
  621. % JumpTo
  622. % Loop
  623. % Fwd/Bkwd Play
  624. ud = get(hfig,'userdata');
  625. isRunning = strcmp(get(ud.htimer,'Running'),'on');
  626. isPaused = ~isRunning && ud.paused;
  627. isStopped = ~isRunning && ~ud.paused;
  628. if isStopped, ena = [1 0 1 1];
  629. elseif isPaused, ena = [1 1 1 1];
  630. else ena = [0 1 1 0];
  631. end
  632. hchild = flipud(get(ud.htoolbar,'children'));
  633. for i=1:4,
  634. if ena(i), s='on'; else s='off'; end
  635. set(hchild(5+i),'enable',s);
  636. end
  637. % --------------------------------------------------------
  638. function htoolbar = CreateButtonBar(hfig)
  639. % Create button bar
  640. % Get a bunch of playback-related icons
  641. icons = mergefields(load('audiotoolbaricons'), load('mplay_icons'));
  642. CR = sprintf('\n');
  643. htoolbar = uitoolbar(hfig); % Create toolbar
  644. setappdata(htoolbar,'icons',icons); % Store icons in toolbar appdata
  645. uipushtool(htoolbar, ...
  646. 'cdata', icons.params, ...
  647. 'tooltip','Properties...', ...
  648. 'click', @cb_properties);
  649. uipushtool(htoolbar, ...
  650. 'cdata', icons.fit_to_view, ...
  651. 'tooltip','True size', ...
  652. 'click', @cb_truesize);
  653. hexp=uipushtool(htoolbar, ...
  654. 'cdata', icons.export_imview, ...
  655. 'tooltip','Export to IMVIEW', ...
  656. 'click', @cb_export_imview);
  657. % Check for IMVIEW
  658. if ~exist('imview','file'),
  659. % set(hexp,'enable','off');
  660. set(hexp,'tooltip', 'Export to Workspace');
  661. end
  662. uipushtool(htoolbar, ...
  663. 'cdata', icons.goto_start_default, ...
  664. 'tooltip','Go to start', ...
  665. 'separator','on', ...
  666. 'click', @cb_goto_start);
  667. uipushtool(htoolbar, ...
  668. 'cdata', icons.rewind_default, ...
  669. 'tooltip','Rewind', ...
  670. 'click', @cb_rewind);
  671. uipushtool(htoolbar, ...
  672. 'cdata', icons.step_back, ...
  673. 'tooltip','Step back', ...
  674. 'click', @cb_step_back);
  675. uipushtool(htoolbar, ...
  676. 'cdata', icons.stop_default, ...
  677. 'tooltip','Stop', ...
  678. 'click', @cb_stop);
  679. uipushtool(htoolbar, ...
  680. 'cdata', icons.play_on, ...
  681. 'tooltip','Play', ...
  682. 'tag','Play/Pause', ...
  683. 'click', @cb_play);
  684. uipushtool(htoolbar, ...
  685. 'cdata', icons.step_fwd, ...
  686. 'tooltip','Step forward', ...
  687. 'click', @cb_step_fwd);
  688. uipushtool(htoolbar, ...
  689. 'cdata', icons.ffwd_default, ...
  690. 'tooltip','Fast forward', ...
  691. 'click', @cb_ffwd);
  692. uipushtool(htoolbar, ...
  693. 'cdata', icons.goto_end_default, ...
  694. 'tooltip','Go to end', ...
  695. 'click', @cb_goto_end);
  696. uipushtool(htoolbar, ...
  697. 'cdata', icons.jump_to, ...
  698. 'separator','on', ...
  699. 'tooltip','Jump to...', ...
  700. 'click', @cb_jumpto);
  701. uipushtool(htoolbar, ...
  702. 'cdata', icons.loop_off, ...
  703. 'tooltip',['Repeat playback'], ...
  704. 'tag','loopbutton', ...
  705. 'click', @cb_loop);
  706. uipushtool(htoolbar, ...
  707. 'cdata', icons.fwdbk_play_off, ...
  708. 'tooltip',['<default>'], ...
  709. 'tag','fbbutton', ...
  710. 'click', @cb_fbmode);
  711. % --------------------------------------------------------
  712. function icons = get_icons_from_fig(hfig)
  713. udfig = get(hfig,'userdata');
  714. udtb = getappdata(udfig.htoolbar);
  715. icons = udtb.icons;
  716. % --------------------------------------------------------
  717. function cb_goto_start(hbutton, eventStruct, hfig)
  718. % goto start button callback
  719. % jump to frame 1, cancel bkwd playback (if on)
  720. if nargin<3, hfig = gcbf; end
  721. ud = get(hfig,'userdata');
  722. if ud.currframe ~= 1, % prevent repeated presses
  723. ud.currframe = 1;
  724. ud.nextframe = 1;
  725. ud.fbrev = 0; % cancel any bkwd playback
  726. set(hfig,'userdata',ud);
  727. ShowMovieFrame(hfig);
  728. end
  729. % --------------------------------------------------------
  730. function cb_rewind(hbutton, eventStruct, hfig)
  731. % Rewind button callback
  732. % Backup "stepsize" frames
  733. if nargin<3, hfig = gcbf; end
  734. ud = get(hfig,'userdata');
  735. stepsize = 10;
  736. if ud.fbmode,
  737. % fwd/back playback mode
  738. if ud.fbrev,
  739. % in reverse ... increment
  740. if ud.currframe >= ud.numFrames-stepsize,
  741. % hit last frame ... go to reverse
  742. ud.currframe = ud.numFrames;
  743. ud.fbrev=0; % no more reverse playback
  744. else
  745. ud.currframe = ud.currframe+stepsize;
  746. end
  747. else
  748. % not in reverse ... decrement
  749. if ud.currframe <= stepsize,
  750. ud.fbrev=1; % hit reverse playback
  751. ud.currframe = stepsize+1; % so next subtraction brings us to frame 1
  752. end
  753. ud.currframe = ud.currframe-stepsize;
  754. end
  755. else
  756. % Not fwd/back mode
  757. ud.currframe = ud.currframe - stepsize;
  758. % Check for backwards wraparound
  759. if ud.currframe < 1,
  760. if ~ud.loopmode,
  761. if ud.currframe == 1-stepsize,
  762. return
  763. end
  764. ud.currframe = 1;
  765. else
  766. ud.currframe = ud.currframe+ud.numFrames;
  767. end
  768. end
  769. end
  770. % Store for next time:
  771. ud.nextframe = ud.currframe;
  772. upd = ~ud.paused;
  773. ud.paused = 1; % assume we're starting from pause
  774. set(hfig,'userdata',ud);
  775. ShowMovieFrame(hfig);
  776. if upd, UpdateGUIControls(hfig); end
  777. % --------------------------------------------------------
  778. function cb_play(hbutton, eventStruct, hfig)
  779. % Play button callback
  780. if nargin<3, hfig = gcbf; end
  781. ud = get(hfig,'userdata');
  782. icons = get_icons_from_fig(hfig);
  783. hPlay = findobj(ud.htoolbar, 'tag','Play/Pause');
  784. % Check if timer is already running
  785. if strcmp(get(ud.htimer,'Running'),'on'),
  786. % Movie already playing
  787. % - Move to Pause mode
  788. % - Show Play icon (currently must be pause indicator)
  789. % Stop timer, set pause mode
  790. ud.paused = 1;
  791. set(hfig,'userdata',ud);
  792. stop(ud.htimer);
  793. % Flush changes
  794. ShowMovieFrame(hfig);
  795. %UpdateFrameReadout(ud);
  796. % Set play icon, darker
  797. set(hPlay, ...
  798. 'tooltip', 'Resume', ...
  799. 'cdata', icons.play_off);
  800. else
  801. % Not running
  802. if ud.paused,
  803. % Paused - move to play
  804. ud.nextframe = ud.currframe;
  805. else
  806. % Stopped - move to play
  807. ud.nextframe = 1; % Start from 1st frame when stopped
  808. ud.fbrev = 0; % Reset fwd/bkwd state to fwd
  809. end
  810. set(hfig,'userdata',ud);
  811. % Show pause icon
  812. set(hPlay, ...
  813. 'tooltip', 'Pause', ...
  814. 'cdata', icons.pause_default);
  815. start(ud.htimer);
  816. end
  817. UpdateGUIControls(hfig);
  818. % --------------------------------------------------------
  819. function cb_stop(hbutton, eventStruct, hfig)
  820. % Stop button callback
  821. if nargin<3, hfig = gcbf; end
  822. ud = get(hfig,'userdata');
  823. ud.paused = 0; % we're stopped, not paused
  824. set(hfig,'userdata',ud);
  825. isRunning = strcmp(get(ud.htimer,'Running'),'on');
  826. if isRunning,
  827. stop(ud.htimer);
  828. else
  829. % Allow stop even when movie not running
  830. % We could have been paused
  831. do_timer_stop(hfig);
  832. end
  833. % --------------------------------------------------------
  834. function cb_step_back(hbutton, eventStruct, hfig)
  835. % Step one frame backward callback
  836. if nargin<3, hfig = gcbf; end
  837. ud = get(hfig,'userdata');
  838. if ud.fbmode,
  839. % fwd/back playback mode
  840. if ud.fbrev,
  841. % in reverse ... increment
  842. if ud.currframe == ud.numFrames-1,
  843. % will hit last frame ... go to normal playback
  844. ud.fbrev=0; % normal playback
  845. end
  846. ud.currframe = ud.currframe+1;
  847. else
  848. % not in reverse ... decrement
  849. if ud.currframe == 1,
  850. % fwd/back hit when frame 2 displayed
  851. % move to frame 1 in non-reverse mode, then go to reverse
  852. % mode
  853. ud.fbrev=1; % enter reverse playback
  854. ud.currframe = 2;
  855. else
  856. ud.currframe = ud.currframe-1;
  857. end
  858. end
  859. else
  860. % Not fwd/back mode
  861. if ud.currframe <= 1,
  862. if ~ud.loopmode,
  863. return
  864. end
  865. ud.currframe = ud.numFrames;
  866. else
  867. ud.currframe = ud.currframe-1;
  868. end
  869. end
  870. ud.nextframe = ud.currframe;
  871. upd = ~ud.paused;
  872. ud.paused = 1; % assume we're starting from pause
  873. set(hfig,'userdata',ud);
  874. ShowMovieFrame(hfig);
  875. if upd, UpdateGUIControls(hfig); end
  876. % --------------------------------------------------------
  877. function cb_step_fwd(hbutton, eventStruct, hfig)
  878. % Step one frame forward callback
  879. % If in fwdbk mode,
  880. % Ignore looping mode
  881. % We always go from fwd to bkwd when step_fwd pressed at last frame
  882. % When we're at frame 1, we must continue to frame 2 regardless of the
  883. % looping setting since we don't know "how" we got there
  884. if nargin<3, hfig = gcbf; end
  885. ud = get(hfig,'userdata');
  886. if ud.fbmode,
  887. % fwd/back playback mode
  888. if ~ud.fbrev,
  889. % not in reverse ... increment fwd
  890. if ud.currframe >= ud.numFrames,
  891. % hit last frame ... go to reverse
  892. ud.currframe = ud.currframe-1;
  893. ud.fbrev=1; % reverse playback
  894. else
  895. ud.currframe = ud.currframe+1;
  896. end
  897. else
  898. % in reverse ... decrement
  899. if ud.currframe == 2,
  900. % fwd/back hit when frame 2 displayed
  901. % move to frame 1 in reverse mode
  902. ud.fbrev=0; % no more reverse playback
  903. end
  904. ud.currframe = ud.currframe-1;
  905. end
  906. else
  907. % Not fwd/back mode
  908. if ud.currframe >= ud.numFrames,
  909. if ~ud.loopmode,
  910. return
  911. end
  912. ud.currframe = 1;
  913. else
  914. ud.currframe = ud.currframe+1;
  915. end
  916. end
  917. ud.nextframe = ud.currframe;
  918. upd = ~ud.paused;
  919. ud.paused = 1; % assume we're starting from pause
  920. set(hfig,'userdata',ud);
  921. ShowMovieFrame(hfig);
  922. if upd, UpdateGUIControls(hfig); end
  923. % --------------------------------------------------------
  924. function cb_ffwd(hbutton, eventStruct, hfig)
  925. % Fast forward button callback
  926. if nargin<3, hfig = gcbf; end
  927. ud = get(hfig,'userdata');
  928. stepsize = 10; %(sazzad_ff)
  929. if ud.fbmode,
  930. % In fwd/rev playback mode
  931. if ~ud.fbrev,
  932. % not in reverse ... increment fwd
  933. if ud.currframe >= ud.numFrames-stepsize,
  934. % hit last frame ... go to reverse
  935. ud.currframe = ud.numFrames;
  936. ud.fbrev=1; % reverse playback
  937. else
  938. ud.currframe = ud.currframe+stepsize;
  939. end
  940. else
  941. % in reverse mode
  942. if ud.currframe <= stepsize,
  943. ud.fbrev=0; % no more reverse playback
  944. ud.currframe = stepsize+1; % so next subtraction brings us to frame 1
  945. end
  946. ud.currframe = ud.currframe-stepsize;
  947. end
  948. else
  949. % Not in fwd/rev playback mode
  950. ud.currframe = ud.currframe + stepsize;
  951. if ud.currframe > ud.numFrames,
  952. if ~ud.loopmode,
  953. if ud.currframe == ud.numFrames+stepsize,
  954. return
  955. end
  956. ud.currframe = ud.numFrames;
  957. else
  958. ud.currframe = ud.currframe-ud.numFrames;
  959. end
  960. end
  961. end
  962. ud.nextframe = ud.currframe;
  963. upd = ~ud.paused;
  964. ud.paused = 1; % assume we're starting from pause
  965. set(hfig,'userdata',ud);
  966. ShowMovieFrame(hfig);
  967. if upd, UpdateGUIControls(hfig); end
  968. % --------------------------------------------------------
  969. function cb_goto_end(hbutton, eventStruct, hfig)
  970. % Goto end button callback
  971. %
  972. % NOTE: For fwd/bkwd mode, goes to last frame as usual,
  973. % and enters bkwd playback. No special code needed.
  974. if nargin<3, hfig = gcbf; end
  975. ud = get(hfig,'userdata');
  976. if ud.currframe ~= ud.numFrames,
  977. ud.currframe = ud.numFrames;
  978. ud.nextframe = ud.currframe;
  979. set(hfig,'userdata',ud);
  980. ShowMovieFrame(hfig);
  981. end
  982. % --------------------------------------------------------
  983. function cb_loop(hbutton, eventStruct, hfig)
  984. % Loop button callback
  985. % Store loopmode state
  986. if nargin<3, hfig = gcbf; end
  987. ud = get(hfig,'userdata');
  988. ud.loopmode = ~ud.loopmode;
  989. set(hfig,'userdata',ud);
  990. ReactToStoredLoopMode(hfig);
  991. % --------------------------------------------------------
  992. function cb_fbmode(hbutton, eventStruct, hfig)
  993. % Fwd/Bkwd playback button callback
  994. % Store state
  995. if nargin<3, hfig = gcbf; end
  996. ud = get(hfig,'userdata');
  997. ud.fbmode = ~ud.fbmode;
  998. ud.fbrev = 0; % Reset direction when fb status changes
  999. set(hfig,'userdata',ud);
  1000. ReactToStoredFBMode(hfig);
  1001. % --------------------------------------------------------
  1002. function cb_truesize(hco, eventStruct, hfig)
  1003. if nargin<3, hfig=gcbf; end
  1004. SetupMovieFrame(hfig);
  1005. % --------------------------------------------------------
  1006. function ReactToStoredLoopMode(hfig)
  1007. icons = get_icons_from_fig(hfig);
  1008. ud = get(hfig,'userdata');
  1009. if ud.loopmode,
  1010. icon = icons.loop_on;
  1011. tip = 'Repeat: On';
  1012. else
  1013. icon = icons.loop_off;
  1014. tip = 'Repeat: Off';
  1015. end
  1016. hLoopButton = findobj(hfig,'tag','loopbutton');
  1017. set(hLoopButton,'cdata',icon,'tooltip',tip);
  1018. % --------------------------------------------------------
  1019. function ReactToStoredFBMode(hfig)
  1020. % Update button icon/tip
  1021. icons = get_icons_from_fig(hfig);
  1022. ud = get(hfig,'userdata');
  1023. if ud.fbmode,
  1024. icon = icons.fwdbk_play_on;
  1025. tip = 'Forward/backward playback';
  1026. else
  1027. icon = icons.fwdbk_play_off;
  1028. tip = 'Normal playback';
  1029. end
  1030. hFBButton = findobj(hfig,'tag','fbbutton');
  1031. set(hFBButton,'cdata',icon,'tooltip',tip);
  1032. % Update frame readout and tooltip
  1033. UpdateFrameReadout(ud);
  1034. UpdateFrameReadoutTooltip(ud);
  1035. % --------------------------------------------------------
  1036. function [r,c,f] = MovieSizeInfo(A, fmt)
  1037. % Determine rows, columns, and frames for each movie format
  1038. % 'S' Standard Movie structure
  1039. % 'I' MxNxF
  1040. % 'RGB' MxNx3xF
  1041. switch fmt
  1042. case 'I'
  1043. r=size(A,1);
  1044. c=size(A,2);
  1045. f=size(A,3);
  1046. case 'RGB'
  1047. r=size(A,1);
  1048. c=size(A,2);
  1049. f=size(A,4);
  1050. case 'S'
  1051. r=size(A(1).cdata,1);
  1052. c=size(A(1).cdata,2);
  1053. f=length(A);
  1054. end
  1055. % --------------------------------------------------------
  1056. function LoadMovie(hfig, A, fmt, varname, fps)
  1057. % Store basic movie info:
  1058. %
  1059. ud = get(hfig,'userdata');
  1060. ud.MovieFormat = fmt;
  1061. ud.Movie = A;
  1062. ud.fps = fps;
  1063. ud.varName = varname;
  1064. [r,c,f] = MovieSizeInfo(A,fmt);
  1065. ud.frameRows = r;
  1066. ud.frameCols = c;
  1067. ud.numFrames = f;
  1068. ud.currframe = 1;
  1069. ud.nextframe = 1;
  1070. % Store data, set name in figure title
  1071. set(hfig, ...
  1072. 'userdata', ud, ...
  1073. 'name', sprintf('Movie Player: %s', ud.varName));
  1074. % Update viewer
  1075. %
  1076. set(hfig,'name', sprintf('Movie Player: %s', ud.varName));
  1077. SetupUpdateFunction(hfig); % Select playback function
  1078. SetupMovieFrame(hfig); % Shrink figure to movie size
  1079. SetupTimer(hfig); % Updates FPS status readout via SetFPS
  1080. ShowMovieFrame(hfig); % Updates frame counter status readout
  1081. UpdateFrameSizeReadout(hfig); % Updates frame size readout
  1082. ReactToStoredLoopMode(hfig); % Initial update of button icon
  1083. ReactToStoredFBMode(hfig); % Initial update of button icon
  1084. % --------------------------------------------------------
  1085. function SetupMovieFrame(hfig)
  1086. % Sets up frame sizes, window sizes, etc
  1087. % Leaves existing image in display
  1088. ud = get(hfig,'userdata');
  1089. rows=ud.frameRows;
  1090. cols=ud.frameCols;
  1091. % Adjust image limits and axis limits appropriately
  1092. set(ud.himage,'xdata', 1:cols, 'ydata', 1:rows);
  1093. % Do a "truesize" like operation
  1094. set(ud.haxis, ...
  1095. 'xlim',[1 cols], ...
  1096. 'ylim',[1 rows], ...
  1097. 'units','pix', ...
  1098. 'pos',[1 1 cols rows]);
  1099. % Set figure to be an exact fit around the axis
  1100. set(ud.hfig,'units','pix');
  1101. figpos = get(ud.hfig,'pos');
  1102. newpos = [figpos(1:2) cols rows];
  1103. set(ud.hfig,'pos',newpos);
  1104. set(ud.haxis,'units','norm'); % allow stretching again
  1105. % --------------------------------------------------------
  1106. function ShowMovieFrame(hfig, fast)
  1107. % Update video image
  1108. ud = get(hfig,'userdata');
  1109. feval(ud.UpdateImageFcn, ud);
  1110. % Update frame counter
  1111. if (nargin > 1) && fast,
  1112. if (ud.currframe==1) || (rem(ud.currframe,10)==0),
  1113. UpdateFrameReadout(ud);
  1114. end
  1115. else
  1116. UpdateFrameReadout(ud);
  1117. end
  1118. % --------------------------------------------------------
  1119. function y = GetExportFrame(ud)
  1120. switch ud.MovieFormat
  1121. case 'I'
  1122. y = ud.Movie(:,:,ud.currframe);
  1123. case 'RGB'
  1124. y = ud.Movie(:,:,:,ud.currframe);
  1125. case 'S'
  1126. y = ud.Movie(ud.currframe).cdata;
  1127. otherwise
  1128. error('Unrecognized movie format.');
  1129. end
  1130. % --------------------------------------------------------
  1131. function UpdateIntensityImage(ud)
  1132. set(ud.himage,'cdata', ud.Movie(:,:,ud.currframe));
  1133. function UpdateRGBImage(ud)
  1134. set(ud.himage,'cdata', ud.Movie(:,:,:,ud.currframe));
  1135. function UpdateStructImage(ud)
  1136. set(ud.himage,'cdata', ud.Movie(ud.currframe).cdata);
  1137. % --------------------------------------------------------
  1138. function SetupUpdateFunction(hfig)
  1139. % Register image update function
  1140. ud = get(hfig,'userdata');
  1141. switch ud.MovieFormat
  1142. case 'I'
  1143. ud.UpdateImageFcn = @UpdateIntensityImage;
  1144. case 'RGB'
  1145. ud.UpdateImageFcn = @UpdateRGBImage;
  1146. case 'S'
  1147. ud.UpdateImageFcn = @UpdateStructImage;
  1148. otherwise
  1149. error('Unrecognized movie format.');
  1150. end
  1151. set(hfig,'userdata',ud);
  1152. % --------------------------------------------------------
  1153. function SetupTimer(hfig)
  1154. % Setup timer
  1155. h = timer( ...
  1156. 'ExecutionMode','fixedRate', ...
  1157. 'TimerFcn', @TimerTickFcn, ...
  1158. 'StopFcn', @TimerStopFcn, ...
  1159. 'BusyMode', 'drop', ...
  1160. 'TasksToExecute', inf);
  1161. % Store fig handle in timer
  1162. udtimer.hfig = hfig;
  1163. set(h,'userdata',udtimer);
  1164. % Store timer handle in figure
  1165. ud = get(hfig,'userdata');
  1166. ud.htimer = h;
  1167. set(hfig,'userdata', ud);
  1168. SetFPS(hfig);
  1169. % --------------------------------------------------------
  1170. function y = ext_getFPS(hfig)
  1171. ud = get(hfig,'userdata');
  1172. y = ud.fps;
  1173. % --------------------------------------------------------
  1174. function ext_setFPS(hfig, fps)
  1175. ud = get(hfig,'userdata');
  1176. ud.fps = fps;
  1177. set(hfig,'userdata',ud);
  1178. SetFPS(hfig);
  1179. % --------------------------------------------------------
  1180. function SetFPS(hfig)
  1181. % Set frames per second for playback
  1182. % Cannot change period while movie is running
  1183. % Must stop timer, change frame rate, then restart timer
  1184. ud = get(hfig,'userdata');
  1185. isRunning = strcmp(get(ud.htimer,'Running'),'on');
  1186. % isPaused = ud.paused;
  1187. if isRunning,
  1188. cb_play([],[],ud.hfig); % pause
  1189. end
  1190. set(ud.htimer,'Period', 1./ud.fps);
  1191. if isRunning,
  1192. cb_play([],[],ud.hfig);
  1193. % ud = get(hfig,'userdata');
  1194. % ud.paused = isPaused;
  1195. % set(hfig,'userdata',ud);
  1196. end
  1197. UpdateFPSReadout(hfig);
  1198. % -------------------------------------------------------------------------
  1199. function UpdateFrameSizeReadout(hfig)
  1200. % Update current frame size readout in status bar
  1201. ud = get(hfig,'UserData');
  1202. sizeStr = sprintf('%dx%d', ud.frameRows, ud.frameCols);
  1203. readoutStr = sprintf('%s:%s', ud.MovieFormat, sizeStr);
  1204. % Build tooltip for frame format/size status bar readout
  1205. switch ud.MovieFormat
  1206. case 'I', s='Intensity';
  1207. case 'S', s='Structure';
  1208. case 'RGB', s='RGB';
  1209. end
  1210. CR = sprintf('\n');
  1211. tipStr = [s ' format' CR sprintf('%d rows x %d cols', ud.frameRows, ud.frameCols)];
  1212. set(ud.hStatusBar.FrameSize,'string',readoutStr,'tooltip',tipStr);
  1213. % -------------------------------------------------------------------------
  1214. function currentFrame=UpdateFrameReadout(ud)
  1215. % Update current frame number readout in status bar
  1216. % If fwd/bkwd mode not on,
  1217. % show "current frame : total frames"
  1218. % If on,
  1219. % show "+/- current frame : total frames"
  1220. % where + means fwd play, - means bkwd play
  1221. %current frame value: currframe, total frame value: numFrames (sazzad)
  1222. str = sprintf('%d:%d',ud.currframe,ud.numFrames);
  1223. if ud.fbmode,
  1224. if ud.fbrev,
  1225. dir='-';
  1226. else
  1227. dir='+';
  1228. end
  1229. str = [dir str];
  1230. end
  1231. getCurrFrame(ud.currframe); % pass current frame number to external func
  1232. set(ud.hStatusBar.FrameNum, 'string', str);
  1233. % -------------------------------------------------------------------------
  1234. function UpdateFrameReadoutTooltip(ud)
  1235. tStr = 'Current Frame : Total Frames';
  1236. if ud.fbmode,
  1237. tStr = [tStr sprintf('\n') '+: Fwd dir, -:Bkwd dir'];
  1238. end
  1239. set(ud.hStatusBar.FrameNum, 'tooltip', tStr);
  1240. % -------------------------------------------------------------------------
  1241. function UpdateFPSReadout(hfig)
  1242. % Update frames per second readout in status bar
  1243. ud = get(hfig,'UserData');
  1244. str = sprintf('FPS: %d',ud.fps);
  1245. set(ud.hStatusBar.FPS,'string',str);
  1246. % --------------------------------------------------------
  1247. function EditProperties(hfig)
  1248. % Get frames per second in dialog box
  1249. ud = get(hfig,'userdata');
  1250. while 1, % infinite loop in case user enters invalid information
  1251. % Get dialog
  1252. prompt={'Desired playback rate (fps):', ...
  1253. 'Colormap expression:'};
  1254. def={num2str(ud.fps), ud.cmapexpr};
  1255. dlgTitle='Movie Player Properties';
  1256. lineNo=1;
  1257. AddOpts.Resize='off';
  1258. AddOpts.WindowStyle='modal';
  1259. AddOpts.Interpreter='none';
  1260. answer=inputdlg(prompt,dlgTitle,lineNo,def,AddOpts);
  1261. if ~isempty(answer), % cancel pressed?
  1262. % Error check
  1263. % Frame rate:
  1264. %
  1265. new_fps = str2num(answer{1});
  1266. if new_fps > 0,
  1267. if ~isequal(new_fps, ud.fps), % change made?
  1268. % Grab userdata now in case changes were made
  1269. % while dialog was open
  1270. ext_setFPS(hfig,new_fps);
  1271. end
  1272. else
  1273. hwarn = warndlg({'Invalid frames/second entered.','Must be > 0.'}, 'Movie Player Error','modal');
  1274. waitfor(hwarn);
  1275. continue;
  1276. end
  1277. % Colormap:
  1278. %
  1279. new_cmapexpr = deblank(answer{2});
  1280. new_cmap = eval(new_cmapexpr, '[]');
  1281. if isempty(new_cmap),
  1282. hwarn = warndlg('Invalid colormap expression.','Movie Player Error','modal');
  1283. waitfor(hwarn);
  1284. continue;
  1285. else
  1286. if ~isequal(new_cmapexpr, ud.cmapexpr), % change made?
  1287. % Grab userdata now in case changes were made
  1288. % while dialog was open
  1289. ud = get(hfig,'userdata');
  1290. ud.cmapexpr = new_cmapexpr;
  1291. ud.cmap = new_cmap;
  1292. set(hfig, 'userdata',ud, 'colormap',new_cmap);
  1293. end
  1294. end
  1295. end
  1296. break % stop infinite loop
  1297. end
  1298. % --------------------------------------------------------
  1299. function EditFrameNum(hfig)
  1300. % Get manually specified frame number in dialog box
  1301. % "Jump to" operation
  1302. % Initialize to last "jump to" value, NOT to the current frame
  1303. % This way, the edit operation becomes useful for continually
  1304. % jumping to a particular frame
  1305. ud = get(hfig,'userdata');
  1306. while 1, % infinite loop in case user enters invalid information
  1307. % Show dialog
  1308. prompt = {'Jump to frame:'};
  1309. def = {num2str(ud.jumpto_frame)};
  1310. dlgTitle = 'Movie Player Properties';
  1311. lineNo = 1;
  1312. AddOpts.Resize = 'off';
  1313. AddOpts.WindowStyle = 'normal';
  1314. AddOpts.Interpreter = 'none';
  1315. answer = inputdlg(prompt,dlgTitle,lineNo,def,AddOpts);
  1316. if ~isempty(answer), % cancel pressed?
  1317. % Error check
  1318. % Currently Displayed Frame:
  1319. %
  1320. new_jumpto = str2num(answer{1});
  1321. if (new_jumpto > 0) && (new_jumpto <= ud.numFrames),
  1322. % Note: always perform update, even if value remains the same
  1323. % That's because the currently displayed frame may have
  1324. % changed behind our backs. Even if we re-grab userdata,
  1325. % it's changing all the time.
  1326. % Get properties again, in case something has
  1327. % changed behind our backs while dialog was open
  1328. ud = get(hfig,'userdata');
  1329. ud.currframe = new_jumpto;
  1330. ud.nextframe = new_jumpto;
  1331. ud.jumpto_frame = new_jumpto;
  1332. % jump puts player in pause mode if currently stopped
  1333. isRunning = strcmp(get(ud.htimer,'Running'),'on');
  1334. isStopped = ~isRunning && ~ud.paused;
  1335. ud.paused = 1;
  1336. set(hfig,'userdata',ud);
  1337. ShowMovieFrame(hfig);
  1338. if isStopped, UpdateGUIControls(hfig); end
  1339. else
  1340. hwarn = warndlg({'Invalid frame number.'}, 'Movie Player Error','modal');
  1341. waitfor(hwarn);
  1342. continue
  1343. end
  1344. end
  1345. break % stop infinite loop
  1346. end
  1347. % --------------------------------------------------------
  1348. function cb_properties(hco, eventStruct)
  1349. EditProperties(gcbf);
  1350. function cb_jumpto(hco, eventStruct)
  1351. EditFrameNum(gcbf);
  1352. % --------------------------------------------------------
  1353. function cb_export_imview(hco, eventStruct)
  1354. % Export current image frame to IMVIEW or base workspace.
  1355. hfig = gcbf;
  1356. ud = get(hfig,'userdata');
  1357. v = GetExportFrame(ud);
  1358. if exist('imview','file'),
  1359. try
  1360. imview(v);
  1361. catch
  1362. warndlg(sprintf('Failed when calling IMVIEW:\n\n%s', lasterr), ...
  1363. 'MPLAY Export Error', 'modal');
  1364. end
  1365. else
  1366. % Export to workspace
  1367. varname = 'mplay_export';
  1368. fprintf(['Exported current image frame to base workspace\n' ...
  1369. 'Variable name: %s\n\n'], varname);
  1370. assignin('base',varname,v);
  1371. end
  1372. % --------------------------------------------------------
  1373. function TimerTickFcn(hco, user)
  1374. ud = get(hco,'userdata'); % hco = timer object
  1375. hfig = ud.hfig;
  1376. ud = get(hfig,'userdata');
  1377. ud.currframe = ud.nextframe;
  1378. ShowMovieFrame(hfig, 1); % "fast" display
  1379. % Increment frame or stop playback if finished
  1380. if (ud.currframe == ud.numFrames),
  1381. % Last frame of movie just displayed
  1382. if ud.fbmode % && ~ud.fbrev, % unnecessary qualifier --- always will be false here
  1383. ud.fbrev = 1; % going into reverse playback mode
  1384. ud.nextframe = ud.currframe-1;
  1385. shouldStop = 0;
  1386. % elseif ud.fbmode && ud.fbrev,
  1387. % error('how did this happen? ==end');
  1388. % shouldStop = 1;
  1389. else
  1390. ud.nextframe = 1; % loop back to beginning
  1391. shouldStop = 1;
  1392. end
  1393. % If we hit this point, the timer ran us to the end of
  1394. % the movie. In particular, the user did not hit stop.
  1395. % Now, if pause is on, it's due to manual interaction with
  1396. % the fwd/back buttons, and not due to actual pausing,
  1397. % obvious since we're still running and is why we're here.
  1398. % Turn off pause:
  1399. ud.paused = 0;
  1400. elseif (ud.currframe == 1),
  1401. % First frame of movie just displayed
  1402. if ud.fbmode && ud.fbrev,
  1403. ud.fbrev = 0; % going into fwd playback mode
  1404. ud.nextframe = ud.currframe+1;
  1405. shouldStop = 1;
  1406. else
  1407. ud.nextframe = 2; % ud.currframe+1
  1408. shouldStop = 0;
  1409. end
  1410. else
  1411. if ud.fbmode && ud.fbrev,
  1412. ud.nextframe = ud.nextframe - 1; % next frame, reverse play
  1413. else
  1414. ud.nextframe = ud.nextframe + 1; % next frame, fwd play
  1415. end
  1416. shouldStop = 0;
  1417. end
  1418. set(hfig,'userdata',ud);
  1419. if shouldStop && ~ud.loopmode, % no looping - stop now
  1420. stop(ud.htimer); % stop playback
  1421. end
  1422. % --------------------------------------------------------
  1423. function TimerStopFcn(hco, user)
  1424. % Keep this here, not in cb_stop
  1425. % Could have stopped from stop button (eg, gone thru cb_stop)
  1426. % but also could have stopped here due to end of movie
  1427. ud = get(hco,'userdata');
  1428. do_timer_stop(ud.hfig);
  1429. % --------------------------------------------------------
  1430. function do_timer_stop(hfig)
  1431. ud = get(hfig,'userdata');
  1432. % ShowMovieFrame(hfig);
  1433. UpdateFrameReadout(ud);
  1434. % Set play icon, brighter
  1435. icons = get_icons_from_fig(hfig);
  1436. hPlay = findobj(ud.htoolbar, 'tag','Play/Pause');
  1437. set(hPlay, ...
  1438. 'tooltip', 'Play', ...
  1439. 'cdata', icons.play_on);
  1440. UpdateGUIControls(hfig);
  1441. % --------------------------------------------------------
  1442. function z = mergefields(varargin)
  1443. %MERGEFIELDS Merge fields into one structure
  1444. % Z = MERGEFIELDS(A,B,C,...) merges all fields of input structures
  1445. % into one structure Z. If common field names exist across input
  1446. % structures, values from later input arguments prevail.
  1447. %
  1448. % Example:
  1449. % x.one=1; x.two=2; % Define structures
  1450. % y.two=-2; y.three=3; % containing a common field (.two)
  1451. % z=mergefields(x,y) % => .one=1, .two=-2, .three=3
  1452. % z=mergefields(y,x) % => .one=1, .two=2, .three=3
  1453. %
  1454. % See also SETFIELD, GETFIELD, RMFIELD, ISFIELD, FIELDNAMES.
  1455. % Copyright 1984-2003 The MathWorks, Inc.
  1456. % $Revision: $ $Date: $
  1457. z=varargin{1};
  1458. for i=2:nargin,
  1459. f=fieldnames(varargin{i});
  1460. for j=1:length(f),
  1461. z.(f{j}) = varargin{i}.(f{j});
  1462. end
  1463. end