function mov = mplay(varargin) %MPLAY Play a movie interactively. % MPLAY(A) opens a new movie player GUI and loads movie data % A into the player. Multiple players may be used at one time. % % MPLAY(A, FMT) explicity specifies a format string FMT for the % movie data, in case a warning from MPLAY(A) indicates ambiguity % in interpreting the format of A. % % MPLAY(A, FPS) or MPLAY(A, FMT, FPS) specifies the default % frame rate, FPS, for the movie, in frames per second. If % omitted, FPS defaults to 30. The GUI supports interactive % changes to FPS as well. % % M=MPLAY(...) returns a MoviePlayerAPI object, M, useful for % programmatic control of the movie player GUI. A list of % all available object methods is obtained from "methods(M)". % % Movie formats % ------------- % Movie A may be one of the following formats: % % Standard MATLAB movie structure (FMT = 'structure' or 'S') % See 'help getframe' for more information on the MATLAB % movie structure. Only movies with empty .colormap field % entries are supported. % % Intensity video array (FMT = 'intensity' or 'I') % 3-D array organized as MxNxF, where each image is of size % MxN and there are F image frames. An input with size % exactly MxNx3 will be interpreted as a 3-frame intensity movie. % % RGB video array (FMT = 'RGB') % 4-D array organized as MxNx3xF, where the R, G, and B % are encoded in the 3rd dimension. Note that MxNx3 is % the usual MATLAB format for an RGB image. % % Video frame data type may be double, uint8, or uint16. % % Keyboard support % ---------------- % P:Play F:FFwd Rt:StepFwd Up:First J:Jump X:FwdBkwd % S:Stop R:Rew Lt:StepRev Dn:Last L:Loop % % EXAMPLE: Playback of standard MATLAB movies. % Run 'crulspin' or 'logospin' from the command line. % These demos create a MATLAB movie structure in the % workspace in variable 'm'. Run "mplay(m)" and be % sure to turn on looping playback. % % See also MOVIE, INT2RGBM, INT2STRUCT, STRUCT2RGBM, IMVIEW. % Copyright 2003 The MathWorks, Inc. % Author: D. Orofino % $Revision: $ $Date: $ % To do: % ------ % - icon for export-to-imview % - API properties: colormap % - Interactive zoom % Note: The following input syntax has been disabled in the % CheckMovieFormat() function. % % Color video components (FMT = @user_fcn) % Cell array containing arrays reprsenting each color plane of a movie, % arranged in a form suitable for a pre-defined conversion function. % In this case, FMT specifies a function (string or function handle) that % converts from the color components to the 4-D RGB video format. The % function is invoked as: RGBM = user_fcn(A{:}). The function must % return a 4-D RGB movie array. If omitted, FMT defaults to @int2rgbm. % % Examples: % MPLAY({R,G,B},@int2rgbm) % converts RGB components to 4-D array % MPLAY({R,G,B},10) % uses int2rgbm by format, 10 frames/sec % MPLAY({Y,U,V},@yuv2rgbm,24) % 24 frames/sec, YUV data format % % GUI Data organization % --------------------- % Figure UserData % .hfig handle to figure window % .haxis handle to axis containing image object % .himage handle to image object % .htoolbar handle to GUI button toolbar % .htimer timer object associated with this player % .hStatusBar structure of handles to parts of status bar % .loopmode 0=no looping, 1=looping % .fbmode 0=no fwd/bkwd playback, 1=fwd/bkwd playback % .fbrev 1=currently in reverse-playback, only if fwd/bkwd flag true % .paused true/false flag indicating that we're in % pause mode --- set to false by pressing play or stop % .nextframe next frame number to display % .currframe current frame displayed in viewer % .jumpto_frame frame number to jump to for frame num edit % .fps requested frame rate (frames per second) % .varName name of variable passed in to player % .numFrames number of frames in movie % .frameRows number of rows in movie image % .frameCols number of columns in movie image % .cmapexpr colormap expr to use during movie playback % .cmap % .UpdateImageFcn function pointer to image update fcn % .Movie movie pixel data % .MovieFormat 'S' Standard movie structure % 'I' MxNxF % 'RGB' MxNx3xF % % Timer Object UserData % .hfig handle to corresponding figure window try, % dfmt: desired movie format, as specified by user [A,dfmt,fps,msg] = parse_inputs(varargin{:}); error(msg); % fmt: actual movie format to use, % string normalized to proper spelling, capitalization, etc [A, fmt] = CheckMovieFormat(A, dfmt); % Create and load GUI with movie hfig = CreateGUI; LoadMovie(hfig, A, fmt, inputname(1), fps); UpdateGUIControls(hfig); AdjustPlayerSize(hfig); % Return object is LHS requested if nargout>0, mov=GetMoviePlayerAPI(hfig); end % Clean up set(hfig,'vis','on'); % time to show the player catch, rethrow(lasterror); end % -------------------------------------------------------- function AdjustPlayerSize(hfig) % Adjust width of player window to be no narrower than % the extent needed to render the button and status bar % % Also, make sure it is no bigger than screen size min_width = 370; % min pixel width to render toolbar set(hfig,'units','pix'); figpos = get(hfig,'pos'); % Widen player to minimum width (if movie is very narrow) if figpos(3) < min_width, figpos(3) = min_width; end % Shrink movie to screen as needed: set(0,'units','pix'); screenpos = get(0,'screensize'); if figpos(3) > screenpos(3), figpos(3) = screenpos(3); end if figpos(4) > screenpos(4), figpos(4) = screenpos(4); end set(hfig,'pos',figpos); % -------------------------------------------------------- function mov = GetMoviePlayerAPI(hfig) fcn.ffwd = @cb_ffwd; fcn.goto_end = @cb_goto_end; fcn.goto_start = @cb_goto_start; fcn.jumpto = @cb_jumpto; fcn.loop = @cb_loop; fcn.fbmode = @cb_fbmode; fcn.play = @cb_play; fcn.rewind = @cb_rewind; fcn.step_back = @cb_step_back; fcn.step_fwd = @cb_step_fwd; fcn.stop = @cb_stop; fcn.truesize = @cb_truesize; fcn.setfps = @ext_setFPS; fcn.getfps = @ext_getFPS; mov = mmovie.player(hfig,fcn); % -------------------------------------------------------- function [A,fmt,fps,msg] = parse_inputs(varargin) %PARSE_INPUTS Parse input arguments % Valid calling syntax: % MPLAY(A) % MPLAY(A, FMT) % MPLAY(A, FPS) % MPLAY(A, FMT, FPS) % % Defaults: A=[]; fmt=''; % no format specified fps=30; % 30 frames per second msg=''; % no errors % Check number of input args msg = nargchk(1,3,nargin); if ~isempty(msg), return; end A = varargin{1}; if nargin > 2, % 3 or more inputs fmt = varargin{2}; fps = varargin{3}; elseif nargin==2 % 2 inputs if ischar(varargin{2}), fmt = varargin{2}; else % must disambiguate: % (A,@my_func) from (A,fps) if isnumeric(varargin{2}), fps = varargin{2}; else fmt = varargin{2}; end end end % Check and expand FMT % Expand the desired format string specified by user % Make it lower case, and complete any partial string specified. % % NOTE: If A is a cell-array, skip this % FMT could be a conversion function % if ~iscell(A), if ~isempty(fmt), if ~ischar(fmt), msg = 'FMT must be a string.'; return end all_in={'intensity','rgb','structure'}; % user format strings all_out={'I','RGB','S'}; % internal format strings i=strmatch(lower(fmt), all_in); if isempty(i), msg='Unrecognized FMT string specified.'; return end fmt=all_out{i}; end end % Check FPS if ~isa(fps,'double') || numel(fps)~=1 || fps<=0, msg='FPS must be a scalar double-precision value > 0.'; return end % -------------------------------------------------------- function [A,fmt,msg] = CheckMovieFormat(A,dfmt) % DetermineMovieFormat % Rules to disambiguate inputs when no format is specified % % Is input a structure? % - 'struct' assumed % check for .colormap and .cdata present % check for empty .colormap entries % check for MxN or MxNx3 sizes in each frame % - otherwise, ERROR % % Is input numeric? % - if not, ERROR % % Is input 4-D? % Are both the 1st and 3rd dims ~= 3 (or empty)? % ERROR % Are both the 1st and 3rd dims == 3? % - assume 'rgb' % - WARN user of ambiguity, and to pass 'rgb' format string % to suppress warning next time % Is the 1st dim = 3 and the 3rd dim ~= 3? % - 'rgbp' assumed % Is the 1st dim ~= 3 and the 3rd dim = 3? % - 'rgb' assumed % % Is input 3-D? % Is the 3rd dim = 3? % WARN that this is being interpreted as a 3-frame intensity movie, % and to pass 'intensity' format string to suppress warning next time % % Is input 2-D? % - 'intensity' assumed, one frame % % Otherwise, ERROR fmt = ''; % default CR = sprintf('\n'); % Check for movie structure format % if isstruct(A), fmt = 'S'; if ~isempty(dfmt) && ~strcmp(fmt,dfmt), error('Movie format (%s) doesn''t match specified format (%s)',fmt,dfmt); end % Check for required fields if ~isfield(A, 'colormap') || ~isfield(A, 'cdata'), error('Invalid movie: structure format does not contain required fields.'); end % Check for empty colormap fields and movie datatypes % - check all frames (thorough but time consuming) % - check just the first frame (quick but incomplete) % i=1; % just check first frame %for i=1:length(A), % check all entries in structure if ~isempty(A(i).colormap), error('All colormap fields in structure format must be empty.'); end c=class(A(i).cdata); switch c, case {'uint8','double'}, otherwise, error('Unsupported data type (%s) found in video frames.', c); end %end return end % Check for cell-array arguments % % NOTE: Disabled color conversion syntax if 0, if iscell(A), % Convert cell array of color components to 4-D RGB video array % using user-defined conversion function % Default if no conversion function specified: int2rgbm if isempty(dfmt), fmt = @int2rgbm; else fmt = dfmt; end % Try to invoke conversion function A = feval(fmt, A{:}); % After the conversion, it is assumed that the video format is RGB fmt = 'RGB'; dfmt = 'RGB'; % Fall-through to standard checking-code for N-D array % after conversion function has completed end end if ~isnumeric(A), error('Unrecognized movie format.'); end % Check for 3-D and 4-D RGB array formats % nd = ndims(A); sz = size(A); if nd==4, A33 = (sz(3)==3); if ~A33, error('Invalid movie format: 3rd dimension of array must be 3.'); end fmt = 'RGB'; if ~isempty(dfmt) && ~strcmp(fmt,dfmt), error('Movie format (%s) doesn''t match specified format (%s)',fmt,dfmt); end return elseif nd==3, A33 = (sz(3)==3); if A33 && isempty(dfmt), warning(['Ambiguous movie format: 3rd dimension of 3-D array is 3.' CR ... 'Assuming ''intensity'' format. Pass format string to suppress warning.']); end fmt='I'; if ~isempty(dfmt) && ~strcmp(fmt,dfmt), error('Movie format (%s) doesn''t match specified format (%s)',fmt,dfmt); end return else % 2-D input fmt='I'; if ~isempty(dfmt) && ~strcmp(fmt,dfmt), error('Movie format (%s) doesn''t match specified format (%s)',fmt,dfmt); end return end % -------------------------------------------------------- function hfig = CreateGUI % Determine renderer mode if 0 & opengl('info'), renderer='opengl'; else renderer='painters'; end % Create figure defaultPos = [50 50 400 400]; hfig = figure(... 'NumberTitle','off', ... 'MenuBar','none', ... 'Renderer',renderer, ... 'HandleVis','callback', ... 'IntegerHandle','off', ... 'KeyPressFcn', @KeypressFcn, ... 'Visible','off', ... 'CloseRequestFcn',@DeleteFcn, ... 'DeleteFcn',@DeleteFcn, ... 'Position',defaultPos, ... 'BackingStore','off', ... 'DoubleBuffer','off'); % Setup movie area defaultN = 64; haxis = axes( ... 'parent',hfig, ... 'pos',[0 0 1 1], ... 'vis','off', ... 'xlim',[1 defaultN], ... 'ylim', [1 defaultN], ... 'ydir','reverse', ... 'xlimmode','manual',... 'ylimmode','manual',... 'zlimmode','manual',... 'climmode','manual',... 'alimmode','manual',... 'layer','bottom',... 'nextplot','add', ... 'dataaspectratio',[1 1 1], ... 'drawmode','fast'); himage = image(... 'parent',haxis, ... 'cdata',zeros(defaultN), ... 'xdata',1:defaultN, ... 'ydata',1:defaultN, ... 'erase','none'); % Setup default figure data % ud = get(hfig,'userdata'); ud.hfig = hfig; ud.haxis = haxis; ud.himage = himage; ud.htoolbar = CreateButtonBar(hfig); ud.htimer = []; ud.hStatusBar = AddStatusBar(hfig); ud.loopmode = 0; % non-looping ud.fbmode = 0; % no fwd/bkwd playback ud.fbrev = 0; % not in rev-playback ud.paused = 0; ud.nextframe = 1; ud.currframe = 0; ud.jumpto_frame = 1; ud.fps = 0; % frames per second ud.varName = ''; % variable name passed to player ud.numFrames = 0; ud.frameRows = 0; ud.frameCols = 0; ud.cmapexpr = 'gray(256)'; % default ud.cmap = gray(256); % default ud.UpdateImageFcn = []; ud.Movie = []; ud.MovieFormat = ''; set(hfig,'userdata', ud); % Finishing touches: % - show GUI % - enable resize fcn set(hfig, ... 'colormap', ud.cmap, ... 'resizefcn', @ResizeFcn); % ------------------------------------------------------------------------- function KeypressFcn(hcb, eventStruct) % Handle keypresses in main window hfig = gcbf; key = get(hfig, 'CurrentChar'); if ~isempty(key), % unix keyboard has an empty key switch lower(key) case char(29) % right cb_step_fwd(hfig,[]); case char(28) % left cb_step_back(hfig,[]); case 'f' cb_ffwd(hfig,[]); case 'r' cb_rewind(hfig,[]); case 's' cb_stop(hfig,[]); case 'p' cb_play(hfig,[]); % play/pause case char(30) % up cb_goto_start(hfig,[]); case char(31) % down cb_goto_end(hfig,[]); case 'j' % jump to EditFrameNum(hfig); case 'l' % loop cb_loop(hfig,[]); case 'x' % fwd/bkwd playback cb_fbmode(hfig,[]); case char(13) % Enter % Open parameters dialog EditProperties(hfig); end end % -------------------------------------------------------- function DeleteFcn(hcb, eventStruct) % How to get here: % Close all force % delete(h) hfig=gcbf; ud = get(hfig,'userdata'); if ~isempty(ud), stop(ud.htimer); % Shut off timer if running end delete(hfig); % Close window % -------------------------------------------------------- function ResizeFcn(hcb, eventStruct) fd = get(hcb,'UserData'); % hcb = hfig hAll = fd.hStatusBar.All; % Get positions and compute resize offsets: fig_pos = get(hcb,'pos'); frame_pos = get(fd.hStatusBar.Region,'pos'); frame_rt = frame_pos(1)+frame_pos(3)-2; delta = fig_pos(3)-frame_rt; % Adjust positions: for i=1:length(hAll), pos = get(hAll(i),'pos'); pos(1) = pos(1) + delta; set(hAll(i),'pos',pos); end % Separately adjust hStatusBar.Region % Grow it wider, don't move it: pos = frame_pos; pos(3)=pos(3)+delta; set(fd.hStatusBar.Region,'pos',pos); % -------------------------------------------------------- function hStatusBar = AddStatusBar(hfig) hfig_pos = get(hfig,'pos'); CR = sprintf('\n'); % Status region frame bg = [1 1 1]*.8; pos=[0 0 hfig_pos(3)+2 22]; hStatusBar.Region = uicontrol('parent',hfig, ... 'style','frame', ... 'units','pix', ... 'pos',pos, ... 'backgr', bg, ... 'foregr', [1 1 1]); % Render right after background frame, so when resizing occurs, % this will be "overwritten" by other data hStatusBar.StatusText = uicontrol('parent',hfig, ... 'style','text', ... 'units','pix', ... 'pos',[2 1 100 16], ... 'string','Ready', ... 'horiz','left', ... 'backgr',bg, ... 'foregr','k'); % Indents for display/trace timing pos1 = [pos(3)-64 1 60 17]; [hStatusBar.FPS, hAll1] = makeStatusBarIndent(hfig,bg,pos1); set(hStatusBar.FPS,'string','FPS: 0', ... 'tooltip' ,['Frames Per Second']); set(hAll1,'ButtonDownFcn',@cb_properties); pos2 = [pos(3)-128 1 60 17]; [hStatusBar.FrameNum, hAll2] = makeStatusBarIndent(hfig,bg,pos2); set(hStatusBar.FrameNum,'string','0:0', ... 'tooltip', ['Current Frame : Total Frames']); set(hAll2,'ButtonDownFcn',@cb_jumpto); pos2 = [pos(3)-148-74 1 90 17]; [hStatusBar.FrameSize, hAll3] = makeStatusBarIndent(hfig,bg,pos2); set(hStatusBar.FrameSize,'string','(FrameSize)', ... 'tooltip', '(framesize readout)'); % set(hAll3,'ButtonDownFcn',@cb_properties); % Group all status bar widget handles together, for resizing: hStatusBar.All = [hAll1 hAll2 hAll3]; % ------------------------------------------------------------------------- function [h, hall] = makeStatusBarIndent(hfig,bg,pos1) hall(1)=uicontrol('parent',hfig, ... 'style','frame', ... 'units','pix', ... 'pos',pos1, ... 'backgr', bg, ... 'foregr', [1 1 1]*.4); pos2=pos1; pos2(4)=1; hall(2)=uicontrol('parent',hfig, ... 'style','frame', ... 'units','pix', ... 'pos',pos2, ... 'backgr', [1 1 1], ... 'foregr', [1 1 1]); pos2=[pos1(1)+pos1(3)-1 pos1(2) 1 pos1(4)]; hall(3)=uicontrol('parent',hfig, ... 'style','frame', ... 'units','pix', ... 'pos',pos2, ... 'backgr', [1 1 1], ... 'foregr', [1 1 1]); hall(4) = uicontrol('parent',hfig, ... 'style','text', ... 'units','pix', ... 'horiz','left', ... 'fontweight','light', ... 'fontsize',8, ... 'pos',pos1+[2 2 -3 -3], ... 'string', 'test', ... 'backgr', bg, ... 'foregr', [0 0 0]); h=hall(4); % main text widget % ------------------------------------------------------------------------- function UpdateStandardStatusText(hfig) % Setup some status bar text, indicating % current scope state % ud = get(hfig,'userdata'); isRunning = strcmp(get(ud.htimer,'Running'),'on'); isPaused = ~isRunning & ud.paused; isStopped = ~isRunning & ~ud.paused; if isStopped, str = 'Stopped'; elseif isPaused, str = 'Paused'; else str = 'Playing'; end UpdateStatusText(hfig,str); % ------------------------------------------------------------------------- function UpdateStatusText(hfig,str) % Set arbitrary text into status region if isempty(hfig), return; end fd = get(hfig,'UserData'); set(fd.hStatusBar.StatusText,'string',str); % -------------------------------------------------------- function UpdateGUIControls(hfig) % Update GUI state, including: % - button enable states/icons % - status bar text UpdateButtonEnables(hfig); UpdateStandardStatusText(hfig); % -------------------------------------------------------- function UpdateButtonEnables(hfig) % Button states: % Enabled=1 % Disabled=0 % stopped paused running % Props (all 1) % Truesz (all 1) % Export (all 1) % % 1st (all 1) % Rew (all 1) % StepRev 1 1 0 % Stop 0 1 1 % Play 1 1 1 % StepFwd 1 1 0 % FFwd (all 1) % Last (all 1) % % JumpTo % Loop % Fwd/Bkwd Play ud = get(hfig,'userdata'); isRunning = strcmp(get(ud.htimer,'Running'),'on'); isPaused = ~isRunning && ud.paused; isStopped = ~isRunning && ~ud.paused; if isStopped, ena = [1 0 1 1]; elseif isPaused, ena = [1 1 1 1]; else ena = [0 1 1 0]; end hchild = flipud(get(ud.htoolbar,'children')); for i=1:4, if ena(i), s='on'; else s='off'; end set(hchild(5+i),'enable',s); end % -------------------------------------------------------- function htoolbar = CreateButtonBar(hfig) % Create button bar % Get a bunch of playback-related icons icons = mergefields(load('audiotoolbaricons'), load('mplay_icons')); CR = sprintf('\n'); htoolbar = uitoolbar(hfig); % Create toolbar setappdata(htoolbar,'icons',icons); % Store icons in toolbar appdata uipushtool(htoolbar, ... 'cdata', icons.params, ... 'tooltip','Properties...', ... 'click', @cb_properties); uipushtool(htoolbar, ... 'cdata', icons.fit_to_view, ... 'tooltip','True size', ... 'click', @cb_truesize); hexp=uipushtool(htoolbar, ... 'cdata', icons.export_imview, ... 'tooltip','Export to IMVIEW', ... 'click', @cb_export_imview); % Check for IMVIEW if ~exist('imview','file'), % set(hexp,'enable','off'); set(hexp,'tooltip', 'Export to Workspace'); end uipushtool(htoolbar, ... 'cdata', icons.goto_start_default, ... 'tooltip','Go to start', ... 'separator','on', ... 'click', @cb_goto_start); uipushtool(htoolbar, ... 'cdata', icons.rewind_default, ... 'tooltip','Rewind', ... 'click', @cb_rewind); uipushtool(htoolbar, ... 'cdata', icons.step_back, ... 'tooltip','Step back', ... 'click', @cb_step_back); uipushtool(htoolbar, ... 'cdata', icons.stop_default, ... 'tooltip','Stop', ... 'click', @cb_stop); uipushtool(htoolbar, ... 'cdata', icons.play_on, ... 'tooltip','Play', ... 'tag','Play/Pause', ... 'click', @cb_play); uipushtool(htoolbar, ... 'cdata', icons.step_fwd, ... 'tooltip','Step forward', ... 'click', @cb_step_fwd); uipushtool(htoolbar, ... 'cdata', icons.ffwd_default, ... 'tooltip','Fast forward', ... 'click', @cb_ffwd); uipushtool(htoolbar, ... 'cdata', icons.goto_end_default, ... 'tooltip','Go to end', ... 'click', @cb_goto_end); uipushtool(htoolbar, ... 'cdata', icons.jump_to, ... 'separator','on', ... 'tooltip','Jump to...', ... 'click', @cb_jumpto); uipushtool(htoolbar, ... 'cdata', icons.loop_off, ... 'tooltip',['Repeat playback'], ... 'tag','loopbutton', ... 'click', @cb_loop); uipushtool(htoolbar, ... 'cdata', icons.fwdbk_play_off, ... 'tooltip',[''], ... 'tag','fbbutton', ... 'click', @cb_fbmode); % -------------------------------------------------------- function icons = get_icons_from_fig(hfig) udfig = get(hfig,'userdata'); udtb = getappdata(udfig.htoolbar); icons = udtb.icons; % -------------------------------------------------------- function cb_goto_start(hbutton, eventStruct, hfig) % goto start button callback % jump to frame 1, cancel bkwd playback (if on) if nargin<3, hfig = gcbf; end ud = get(hfig,'userdata'); if ud.currframe ~= 1, % prevent repeated presses ud.currframe = 1; ud.nextframe = 1; ud.fbrev = 0; % cancel any bkwd playback set(hfig,'userdata',ud); ShowMovieFrame(hfig); end % -------------------------------------------------------- function cb_rewind(hbutton, eventStruct, hfig) % Rewind button callback % Backup "stepsize" frames if nargin<3, hfig = gcbf; end ud = get(hfig,'userdata'); stepsize = 10; if ud.fbmode, % fwd/back playback mode if ud.fbrev, % in reverse ... increment if ud.currframe >= ud.numFrames-stepsize, % hit last frame ... go to reverse ud.currframe = ud.numFrames; ud.fbrev=0; % no more reverse playback else ud.currframe = ud.currframe+stepsize; end else % not in reverse ... decrement if ud.currframe <= stepsize, ud.fbrev=1; % hit reverse playback ud.currframe = stepsize+1; % so next subtraction brings us to frame 1 end ud.currframe = ud.currframe-stepsize; end else % Not fwd/back mode ud.currframe = ud.currframe - stepsize; % Check for backwards wraparound if ud.currframe < 1, if ~ud.loopmode, if ud.currframe == 1-stepsize, return end ud.currframe = 1; else ud.currframe = ud.currframe+ud.numFrames; end end end % Store for next time: ud.nextframe = ud.currframe; upd = ~ud.paused; ud.paused = 1; % assume we're starting from pause set(hfig,'userdata',ud); ShowMovieFrame(hfig); if upd, UpdateGUIControls(hfig); end % -------------------------------------------------------- function cb_play(hbutton, eventStruct, hfig) % Play button callback if nargin<3, hfig = gcbf; end ud = get(hfig,'userdata'); icons = get_icons_from_fig(hfig); hPlay = findobj(ud.htoolbar, 'tag','Play/Pause'); % Check if timer is already running if strcmp(get(ud.htimer,'Running'),'on'), % Movie already playing % - Move to Pause mode % - Show Play icon (currently must be pause indicator) % Stop timer, set pause mode ud.paused = 1; set(hfig,'userdata',ud); stop(ud.htimer); % Flush changes ShowMovieFrame(hfig); %UpdateFrameReadout(ud); % Set play icon, darker set(hPlay, ... 'tooltip', 'Resume', ... 'cdata', icons.play_off); else % Not running if ud.paused, % Paused - move to play ud.nextframe = ud.currframe; else % Stopped - move to play ud.nextframe = 1; % Start from 1st frame when stopped ud.fbrev = 0; % Reset fwd/bkwd state to fwd end set(hfig,'userdata',ud); % Show pause icon set(hPlay, ... 'tooltip', 'Pause', ... 'cdata', icons.pause_default); start(ud.htimer); end UpdateGUIControls(hfig); % -------------------------------------------------------- function cb_stop(hbutton, eventStruct, hfig) % Stop button callback if nargin<3, hfig = gcbf; end ud = get(hfig,'userdata'); ud.paused = 0; % we're stopped, not paused set(hfig,'userdata',ud); isRunning = strcmp(get(ud.htimer,'Running'),'on'); if isRunning, stop(ud.htimer); else % Allow stop even when movie not running % We could have been paused do_timer_stop(hfig); end % -------------------------------------------------------- function cb_step_back(hbutton, eventStruct, hfig) % Step one frame backward callback if nargin<3, hfig = gcbf; end ud = get(hfig,'userdata'); if ud.fbmode, % fwd/back playback mode if ud.fbrev, % in reverse ... increment if ud.currframe == ud.numFrames-1, % will hit last frame ... go to normal playback ud.fbrev=0; % normal playback end ud.currframe = ud.currframe+1; else % not in reverse ... decrement if ud.currframe == 1, % fwd/back hit when frame 2 displayed % move to frame 1 in non-reverse mode, then go to reverse % mode ud.fbrev=1; % enter reverse playback ud.currframe = 2; else ud.currframe = ud.currframe-1; end end else % Not fwd/back mode if ud.currframe <= 1, if ~ud.loopmode, return end ud.currframe = ud.numFrames; else ud.currframe = ud.currframe-1; end end ud.nextframe = ud.currframe; upd = ~ud.paused; ud.paused = 1; % assume we're starting from pause set(hfig,'userdata',ud); ShowMovieFrame(hfig); if upd, UpdateGUIControls(hfig); end % -------------------------------------------------------- function cb_step_fwd(hbutton, eventStruct, hfig) % Step one frame forward callback % If in fwdbk mode, % Ignore looping mode % We always go from fwd to bkwd when step_fwd pressed at last frame % When we're at frame 1, we must continue to frame 2 regardless of the % looping setting since we don't know "how" we got there if nargin<3, hfig = gcbf; end ud = get(hfig,'userdata'); if ud.fbmode, % fwd/back playback mode if ~ud.fbrev, % not in reverse ... increment fwd if ud.currframe >= ud.numFrames, % hit last frame ... go to reverse ud.currframe = ud.currframe-1; ud.fbrev=1; % reverse playback else ud.currframe = ud.currframe+1; end else % in reverse ... decrement if ud.currframe == 2, % fwd/back hit when frame 2 displayed % move to frame 1 in reverse mode ud.fbrev=0; % no more reverse playback end ud.currframe = ud.currframe-1; end else % Not fwd/back mode if ud.currframe >= ud.numFrames, if ~ud.loopmode, return end ud.currframe = 1; else ud.currframe = ud.currframe+1; end end ud.nextframe = ud.currframe; upd = ~ud.paused; ud.paused = 1; % assume we're starting from pause set(hfig,'userdata',ud); ShowMovieFrame(hfig); if upd, UpdateGUIControls(hfig); end % -------------------------------------------------------- function cb_ffwd(hbutton, eventStruct, hfig) % Fast forward button callback if nargin<3, hfig = gcbf; end ud = get(hfig,'userdata'); stepsize = 10; if ud.fbmode, % In fwd/rev playback mode if ~ud.fbrev, % not in reverse ... increment fwd if ud.currframe >= ud.numFrames-stepsize, % hit last frame ... go to reverse ud.currframe = ud.numFrames; ud.fbrev=1; % reverse playback else ud.currframe = ud.currframe+stepsize; end else % in reverse mode if ud.currframe <= stepsize, ud.fbrev=0; % no more reverse playback ud.currframe = stepsize+1; % so next subtraction brings us to frame 1 end ud.currframe = ud.currframe-stepsize; end else % Not in fwd/rev playback mode ud.currframe = ud.currframe + stepsize; if ud.currframe > ud.numFrames, if ~ud.loopmode, if ud.currframe == ud.numFrames+stepsize, return end ud.currframe = ud.numFrames; else ud.currframe = ud.currframe-ud.numFrames; end end end ud.nextframe = ud.currframe; upd = ~ud.paused; ud.paused = 1; % assume we're starting from pause set(hfig,'userdata',ud); ShowMovieFrame(hfig); if upd, UpdateGUIControls(hfig); end % -------------------------------------------------------- function cb_goto_end(hbutton, eventStruct, hfig) % Goto end button callback % % NOTE: For fwd/bkwd mode, goes to last frame as usual, % and enters bkwd playback. No special code needed. if nargin<3, hfig = gcbf; end ud = get(hfig,'userdata'); if ud.currframe ~= ud.numFrames, ud.currframe = ud.numFrames; ud.nextframe = ud.currframe; set(hfig,'userdata',ud); ShowMovieFrame(hfig); end % -------------------------------------------------------- function cb_loop(hbutton, eventStruct, hfig) % Loop button callback % Store loopmode state if nargin<3, hfig = gcbf; end ud = get(hfig,'userdata'); ud.loopmode = ~ud.loopmode; set(hfig,'userdata',ud); ReactToStoredLoopMode(hfig); % -------------------------------------------------------- function cb_fbmode(hbutton, eventStruct, hfig) % Fwd/Bkwd playback button callback % Store state if nargin<3, hfig = gcbf; end ud = get(hfig,'userdata'); ud.fbmode = ~ud.fbmode; ud.fbrev = 0; % Reset direction when fb status changes set(hfig,'userdata',ud); ReactToStoredFBMode(hfig); % -------------------------------------------------------- function cb_truesize(hco, eventStruct, hfig) if nargin<3, hfig=gcbf; end SetupMovieFrame(hfig); % -------------------------------------------------------- function ReactToStoredLoopMode(hfig) icons = get_icons_from_fig(hfig); ud = get(hfig,'userdata'); if ud.loopmode, icon = icons.loop_on; tip = 'Repeat: On'; else icon = icons.loop_off; tip = 'Repeat: Off'; end hLoopButton = findobj(hfig,'tag','loopbutton'); set(hLoopButton,'cdata',icon,'tooltip',tip); % -------------------------------------------------------- function ReactToStoredFBMode(hfig) % Update button icon/tip icons = get_icons_from_fig(hfig); ud = get(hfig,'userdata'); if ud.fbmode, icon = icons.fwdbk_play_on; tip = 'Forward/backward playback'; else icon = icons.fwdbk_play_off; tip = 'Normal playback'; end hFBButton = findobj(hfig,'tag','fbbutton'); set(hFBButton,'cdata',icon,'tooltip',tip); % Update frame readout and tooltip UpdateFrameReadout(ud); UpdateFrameReadoutTooltip(ud); % -------------------------------------------------------- function [r,c,f] = MovieSizeInfo(A, fmt) % Determine rows, columns, and frames for each movie format % 'S' Standard Movie structure % 'I' MxNxF % 'RGB' MxNx3xF switch fmt case 'I' r=size(A,1); c=size(A,2); f=size(A,3); case 'RGB' r=size(A,1); c=size(A,2); f=size(A,4); case 'S' r=size(A(1).cdata,1); c=size(A(1).cdata,2); f=length(A); end % -------------------------------------------------------- function LoadMovie(hfig, A, fmt, varname, fps) % Store basic movie info: % ud = get(hfig,'userdata'); ud.MovieFormat = fmt; ud.Movie = A; ud.fps = fps; ud.varName = varname; [r,c,f] = MovieSizeInfo(A,fmt); ud.frameRows = r; ud.frameCols = c; ud.numFrames = f; ud.currframe = 1; ud.nextframe = 1; % Store data, set name in figure title set(hfig, ... 'userdata', ud, ... 'name', sprintf('Movie Player: %s', ud.varName)); % Update viewer % set(hfig,'name', sprintf('Movie Player: %s', ud.varName)); SetupUpdateFunction(hfig); % Select playback function SetupMovieFrame(hfig); % Shrink figure to movie size SetupTimer(hfig); % Updates FPS status readout via SetFPS ShowMovieFrame(hfig); % Updates frame counter status readout UpdateFrameSizeReadout(hfig); % Updates frame size readout ReactToStoredLoopMode(hfig); % Initial update of button icon ReactToStoredFBMode(hfig); % Initial update of button icon % -------------------------------------------------------- function SetupMovieFrame(hfig) % Sets up frame sizes, window sizes, etc % Leaves existing image in display ud = get(hfig,'userdata'); rows=ud.frameRows; cols=ud.frameCols; % Adjust image limits and axis limits appropriately set(ud.himage,'xdata', 1:cols, 'ydata', 1:rows); % Do a "truesize" like operation set(ud.haxis, ... 'xlim',[1 cols], ... 'ylim',[1 rows], ... 'units','pix', ... 'pos',[1 1 cols rows]); % Set figure to be an exact fit around the axis set(ud.hfig,'units','pix'); figpos = get(ud.hfig,'pos'); newpos = [figpos(1:2) cols rows]; set(ud.hfig,'pos',newpos); set(ud.haxis,'units','norm'); % allow stretching again % -------------------------------------------------------- function ShowMovieFrame(hfig, fast) % Update video image ud = get(hfig,'userdata'); feval(ud.UpdateImageFcn, ud); % Update frame counter if (nargin > 1) && fast, if (ud.currframe==1) || (rem(ud.currframe,10)==0), UpdateFrameReadout(ud); end else UpdateFrameReadout(ud); end % -------------------------------------------------------- function y = GetExportFrame(ud) switch ud.MovieFormat case 'I' y = ud.Movie(:,:,ud.currframe); case 'RGB' y = ud.Movie(:,:,:,ud.currframe); case 'S' y = ud.Movie(ud.currframe).cdata; otherwise error('Unrecognized movie format.'); end % -------------------------------------------------------- function UpdateIntensityImage(ud) set(ud.himage,'cdata', ud.Movie(:,:,ud.currframe)); function UpdateRGBImage(ud) set(ud.himage,'cdata', ud.Movie(:,:,:,ud.currframe)); function UpdateStructImage(ud) set(ud.himage,'cdata', ud.Movie(ud.currframe).cdata); % -------------------------------------------------------- function SetupUpdateFunction(hfig) % Register image update function ud = get(hfig,'userdata'); switch ud.MovieFormat case 'I' ud.UpdateImageFcn = @UpdateIntensityImage; case 'RGB' ud.UpdateImageFcn = @UpdateRGBImage; case 'S' ud.UpdateImageFcn = @UpdateStructImage; otherwise error('Unrecognized movie format.'); end set(hfig,'userdata',ud); % -------------------------------------------------------- function SetupTimer(hfig) % Setup timer h = timer( ... 'ExecutionMode','fixedRate', ... 'TimerFcn', @TimerTickFcn, ... 'StopFcn', @TimerStopFcn, ... 'BusyMode', 'drop', ... 'TasksToExecute', inf); % Store fig handle in timer udtimer.hfig = hfig; set(h,'userdata',udtimer); % Store timer handle in figure ud = get(hfig,'userdata'); ud.htimer = h; set(hfig,'userdata', ud); SetFPS(hfig); % -------------------------------------------------------- function y = ext_getFPS(hfig) ud = get(hfig,'userdata'); y = ud.fps; % -------------------------------------------------------- function ext_setFPS(hfig, fps) ud = get(hfig,'userdata'); ud.fps = fps; set(hfig,'userdata',ud); SetFPS(hfig); % -------------------------------------------------------- function SetFPS(hfig) % Set frames per second for playback % Cannot change period while movie is running % Must stop timer, change frame rate, then restart timer ud = get(hfig,'userdata'); isRunning = strcmp(get(ud.htimer,'Running'),'on'); % isPaused = ud.paused; if isRunning, cb_play([],[],ud.hfig); % pause end set(ud.htimer,'Period', 1./ud.fps); if isRunning, cb_play([],[],ud.hfig); % ud = get(hfig,'userdata'); % ud.paused = isPaused; % set(hfig,'userdata',ud); end UpdateFPSReadout(hfig); % ------------------------------------------------------------------------- function UpdateFrameSizeReadout(hfig) % Update current frame size readout in status bar ud = get(hfig,'UserData'); sizeStr = sprintf('%dx%d', ud.frameRows, ud.frameCols); readoutStr = sprintf('%s:%s', ud.MovieFormat, sizeStr); % Build tooltip for frame format/size status bar readout switch ud.MovieFormat case 'I', s='Intensity'; case 'S', s='Structure'; case 'RGB', s='RGB'; end CR = sprintf('\n'); tipStr = [s ' format' CR sprintf('%d rows x %d cols', ud.frameRows, ud.frameCols)]; set(ud.hStatusBar.FrameSize,'string',readoutStr,'tooltip',tipStr); % ------------------------------------------------------------------------- function UpdateFrameReadout(ud) % Update current frame number readout in status bar % If fwd/bkwd mode not on, % show "current frame : total frames" % If on, % show "+/- current frame : total frames" % where + means fwd play, - means bkwd play str = sprintf('%d:%d',ud.currframe,ud.numFrames); if ud.fbmode, if ud.fbrev, dir='-'; else dir='+'; end str = [dir str]; end set(ud.hStatusBar.FrameNum, 'string', str); % ------------------------------------------------------------------------- function UpdateFrameReadoutTooltip(ud) tStr = 'Current Frame : Total Frames'; if ud.fbmode, tStr = [tStr sprintf('\n') '+: Fwd dir, -:Bkwd dir']; end set(ud.hStatusBar.FrameNum, 'tooltip', tStr); % ------------------------------------------------------------------------- function UpdateFPSReadout(hfig) % Update frames per second readout in status bar ud = get(hfig,'UserData'); str = sprintf('FPS: %d',ud.fps); set(ud.hStatusBar.FPS,'string',str); % -------------------------------------------------------- function EditProperties(hfig) % Get frames per second in dialog box ud = get(hfig,'userdata'); while 1, % infinite loop in case user enters invalid information % Get dialog prompt={'Desired playback rate (fps):', ... 'Colormap expression:'}; def={num2str(ud.fps), ud.cmapexpr}; dlgTitle='Movie Player Properties'; lineNo=1; AddOpts.Resize='off'; AddOpts.WindowStyle='modal'; AddOpts.Interpreter='none'; answer=inputdlg(prompt,dlgTitle,lineNo,def,AddOpts); if ~isempty(answer), % cancel pressed? % Error check % Frame rate: % new_fps = str2num(answer{1}); if new_fps > 0, if ~isequal(new_fps, ud.fps), % change made? % Grab userdata now in case changes were made % while dialog was open ext_setFPS(hfig,new_fps); end else hwarn = warndlg({'Invalid frames/second entered.','Must be > 0.'}, 'Movie Player Error','modal'); waitfor(hwarn); continue; end % Colormap: % new_cmapexpr = deblank(answer{2}); new_cmap = eval(new_cmapexpr, '[]'); if isempty(new_cmap), hwarn = warndlg('Invalid colormap expression.','Movie Player Error','modal'); waitfor(hwarn); continue; else if ~isequal(new_cmapexpr, ud.cmapexpr), % change made? % Grab userdata now in case changes were made % while dialog was open ud = get(hfig,'userdata'); ud.cmapexpr = new_cmapexpr; ud.cmap = new_cmap; set(hfig, 'userdata',ud, 'colormap',new_cmap); end end end break % stop infinite loop end % -------------------------------------------------------- function EditFrameNum(hfig) % Get manually specified frame number in dialog box % "Jump to" operation % Initialize to last "jump to" value, NOT to the current frame % This way, the edit operation becomes useful for continually % jumping to a particular frame ud = get(hfig,'userdata'); while 1, % infinite loop in case user enters invalid information % Show dialog prompt = {'Jump to frame:'}; def = {num2str(ud.jumpto_frame)}; dlgTitle = 'Movie Player Properties'; lineNo = 1; AddOpts.Resize = 'off'; AddOpts.WindowStyle = 'normal'; AddOpts.Interpreter = 'none'; answer = inputdlg(prompt,dlgTitle,lineNo,def,AddOpts); if ~isempty(answer), % cancel pressed? % Error check % Currently Displayed Frame: % new_jumpto = str2num(answer{1}); if (new_jumpto > 0) && (new_jumpto <= ud.numFrames), % Note: always perform update, even if value remains the same % That's because the currently displayed frame may have % changed behind our backs. Even if we re-grab userdata, % it's changing all the time. % Get properties again, in case something has % changed behind our backs while dialog was open ud = get(hfig,'userdata'); ud.currframe = new_jumpto; ud.nextframe = new_jumpto; ud.jumpto_frame = new_jumpto; % jump puts player in pause mode if currently stopped isRunning = strcmp(get(ud.htimer,'Running'),'on'); isStopped = ~isRunning && ~ud.paused; ud.paused = 1; set(hfig,'userdata',ud); ShowMovieFrame(hfig); if isStopped, UpdateGUIControls(hfig); end else hwarn = warndlg({'Invalid frame number.'}, 'Movie Player Error','modal'); waitfor(hwarn); continue end end break % stop infinite loop end % -------------------------------------------------------- function cb_properties(hco, eventStruct) EditProperties(gcbf); function cb_jumpto(hco, eventStruct) EditFrameNum(gcbf); % -------------------------------------------------------- function cb_export_imview(hco, eventStruct) % Export current image frame to IMVIEW or base workspace. hfig = gcbf; ud = get(hfig,'userdata'); v = GetExportFrame(ud); if exist('imview','file'), try imview(v); catch warndlg(sprintf('Failed when calling IMVIEW:\n\n%s', lasterr), ... 'MPLAY Export Error', 'modal'); end else % Export to workspace varname = 'mplay_export'; fprintf(['Exported current image frame to base workspace\n' ... 'Variable name: %s\n\n'], varname); assignin('base',varname,v); end % -------------------------------------------------------- function TimerTickFcn(hco, user) ud = get(hco,'userdata'); % hco = timer object hfig = ud.hfig; ud = get(hfig,'userdata'); ud.currframe = ud.nextframe; ShowMovieFrame(hfig, 1); % "fast" display % Increment frame or stop playback if finished if (ud.currframe == ud.numFrames), % Last frame of movie just displayed if ud.fbmode % && ~ud.fbrev, % unnecessary qualifier --- always will be false here ud.fbrev = 1; % going into reverse playback mode ud.nextframe = ud.currframe-1; shouldStop = 0; % elseif ud.fbmode && ud.fbrev, % error('how did this happen? ==end'); % shouldStop = 1; else ud.nextframe = 1; % loop back to beginning shouldStop = 1; end % If we hit this point, the timer ran us to the end of % the movie. In particular, the user did not hit stop. % Now, if pause is on, it's due to manual interaction with % the fwd/back buttons, and not due to actual pausing, % obvious since we're still running and is why we're here. % Turn off pause: ud.paused = 0; elseif (ud.currframe == 1), % First frame of movie just displayed if ud.fbmode && ud.fbrev, ud.fbrev = 0; % going into fwd playback mode ud.nextframe = ud.currframe+1; shouldStop = 1; else ud.nextframe = 2; % ud.currframe+1 shouldStop = 0; end else if ud.fbmode && ud.fbrev, ud.nextframe = ud.nextframe - 1; % next frame, reverse play else ud.nextframe = ud.nextframe + 1; % next frame, fwd play end shouldStop = 0; end set(hfig,'userdata',ud); if shouldStop && ~ud.loopmode, % no looping - stop now stop(ud.htimer); % stop playback end % -------------------------------------------------------- function TimerStopFcn(hco, user) % Keep this here, not in cb_stop % Could have stopped from stop button (eg, gone thru cb_stop) % but also could have stopped here due to end of movie ud = get(hco,'userdata'); do_timer_stop(ud.hfig); % -------------------------------------------------------- function do_timer_stop(hfig) ud = get(hfig,'userdata'); % ShowMovieFrame(hfig); UpdateFrameReadout(ud); % Set play icon, brighter icons = get_icons_from_fig(hfig); hPlay = findobj(ud.htoolbar, 'tag','Play/Pause'); set(hPlay, ... 'tooltip', 'Play', ... 'cdata', icons.play_on); UpdateGUIControls(hfig); % -------------------------------------------------------- function z = mergefields(varargin) %MERGEFIELDS Merge fields into one structure % Z = MERGEFIELDS(A,B,C,...) merges all fields of input structures % into one structure Z. If common field names exist across input % structures, values from later input arguments prevail. % % Example: % x.one=1; x.two=2; % Define structures % y.two=-2; y.three=3; % containing a common field (.two) % z=mergefields(x,y) % => .one=1, .two=-2, .three=3 % z=mergefields(y,x) % => .one=1, .two=2, .three=3 % % See also SETFIELD, GETFIELD, RMFIELD, ISFIELD, FIELDNAMES. % Copyright 1984-2003 The MathWorks, Inc. % $Revision: $ $Date: $ z=varargin{1}; for i=2:nargin, f=fieldnames(varargin{i}); for j=1:length(f), z.(f{j}) = varargin{i}.(f{j}); end end % [EOF] mplay.m e-REdING. Biblioteca de la Escuela Superior de Ingenieros de Sevilla.


DESARROLLO Y PUESTA EN FUNCIONAMIENTO DE UN SISTEMA DE MONITORIZACIÓN MÚLTIPLE DE MAGNITUDES BIOFÍSICAS

: Lozano Sánchez, Mª Carmen
: Ingeniería Telecomunicación
Contenido del proyecto: