Code covered by the BSD License  

Highlights from
ALARM

image thumbnail
from ALARM by Jiro Doke
An alarm function that displays a dialog box after a set length of time.

alarm(t, msg, varargin)
function out = alarm(t, msg, varargin)

%ALARM  Displays an alarm message after a set time.
%   ALARM(T, MSG) displays a message after T seconds with a text message
%   MSG. After T seconds, the computer will start beeping and display a
%   dialog box with an option to Snooze. The beeping will stop after one
%   minute or when the dialog box is closed. The snooze interval is 5
%   minutes and up to 10 snoozes are allowed. These values can be changed
%   by ALARM(T, MSG, PROP, VAL, ...) where PROP can be one of the two:
%
%     'SnoozeInt'   : snooze interval in seconds (default: 300)
%     'SnoozeCount' : number of maximum snoozes (default: 10)
%
%   T can also be a string of a specific time for the alarm. The string may
%   be any of the following formats:
%       HH:MM, HH:MM:SS, HH:MM PM, HH:MM:SS PM.
%   If the date is specified, it is ignored. The alarm will go off at the
%   next possible HH:MM:SS.
%
%   The dialog box is a QUESTDLG, which means that all execution will be
%   halted until the user selects one of the buttons.
%
%   ALARM by itself will list all active alarms. It will display whether
%   the alarm has not yet gone off (pending) or has been snoozed, the time
%   til the next alarm, and the alarm message.
%
%   ALARM('-delete') will display the active alarms and give the option of
%   deleting any of the alarms.
%
%   When an ALARM is initially defined, it can return the number of seconds
%   before it will go off. Use semicolon to suppress this output.
%
%   This code uses a timer object, and it will delete itself once the alarm
%   is turned off. Note that the timer can be deleted. When MATLAB closes,
%   it will also be deleted and will NOT be restored at the next session.
%   The purpose of this code is for a simple time reminder function for
%   those long coding sessions one might have.
%
% Example:
%   % alarm in 60 seconds
%   alarm(60, 'You can stop waiting now');
%
%   % alarm at 9 PM
%   alarm('9:00 PM', 'It''s 9 PM!!');
%
%   % snooze time of 3 minutes for a max of 5 snoozes
%   alarm(120, 'Hello!', 'SnoozeInt', 180, 'SnoozeCount', 5);
%
% See also TIMER

%   VERSIONS:
%     v1.0 - first version
%     v2.0 - added option to view and delete active alarms.
%     v2.1 - added 1-min beeping until dialog box is closed. This behaves
%            more like an alarm clock.
%     v3.0 - added option to specify a time. (12/6/2005)
%     v3.1 - minor code change, from MLINT (Mar 2, 2006)
%     v3.2 - only use the HH:MM:SS information. (April 22, 2006)
%     v3.3 - set the ObjectVisibility to off (June, 2007)
%     v3.31- added examples (June, 2008)
%
% Jiro Doke
% Copyright The MathWorks, Inc.
% November 2005

if nargin == 0          % view active alarms
  findAlarm('view');
  return;  
end

if nargin == 1 && ischar(t)
  if strcmpi(t, '-delete')
    findAlarm('delete');
    return;
  end
end

if nargin < 2
  msg = 'This is an Alarm Clock!';
end

if ischar(t)  % it may be a time string -- convert to time in seconds
  curT_vec = clock;
  try
    c = datevec(t);
  catch ME1
    fprintf('Invalid TIME string: ''%s''.\n', t);
    rethrow(ME1);
  end
  % ignore the date (1st 3 elements).
  if datenum([0 0 0, c(4:end)]) > datenum([0 0 0, curT_vec(4:end)])
    % the time is after current time
    c = [curT_vec(1:3), c(4:end)];
  else
    % the time is before, meaning it may be on the next day
    cc = datevec(datenum(curT_vec(1:3))+1); % add one day
    c = [cc(1:3), c(4:end)];
  end
  
  t = etime(c, curT_vec);
end
if ~isnumeric(t) || ~ischar(msg)
  error('T must be time in seconds and MSG must be a string');
end

% default values
st = 300; % snooze interval in seconds
sc = 10;  % number of snoozes

%% Optional input arguments
if nargin > 2
  vars = varargin;
  nvar = length(varargin);
  if mod(nvar, 2)
    error('Optional arguments must be in PROP/VAL pairs');
  end
  while ~isempty(vars)
    if ischar(vars{1})
      switch lower(vars{1})
        
        case 'snoozeint'  % snooze interval
          st = vars{2};
          
        case 'snoozecount'  % number of snoozes
          sc = vars{2};
          
        otherwise
          error('Invalid PROPERTY');
          
      end
      vars(1:2) = '';
    else
      error('Invalid PROPERTY');
    end
  end
end

if ~(isnumeric(st) && numel(st) == 1) || ~(isnumeric(sc) && numel(sc) == 1)
  error('SnoozeInt and SnoozeCount must be a scalar');
end

%% Create timer object
tm = timer(...
  'Name'            , 'Alarm Clock',        ...
  'Period'          , st,                   ...  % snooze interval in seconds
  'StartDelay'      , t,                    ...  % alarm in t seconds
  'TasksToExecute'  , sc,                   ...  % number of snoozes
  'ExecutionMode'   , 'fixedSpacing',       ...
  'ObjectVisibility', 'off',                ...
  'TimerFcn'        , {@displayAlarm, msg}, ...
  'StopFcn'         , @deleteAlarm,         ...
  'tag'             , datestr(now));


%% Start alarm timer
start(tm);

if nargout == 1
  out = t;
end

%--------------------------------------------------------------------------
%--------------------------------------------------------------------------
function displayAlarm(obj, edata, msg) %#ok

% beeping sound
t         = 0:1/8192:60;      % beep for 1 minute
x         = 0.25*sin(3000*t);
y         = sin(4*pi*t);      % 2 Hz wave
x(y < 0)  = 0;                % use this to create breaks in the sound
sound(x);

if get(obj, 'TasksExecuted') == get(obj, 'TasksToExecute')  % Reached maximum limit for snooze
  btn = questdlg({datestr(now), msg}, ...
    sprintf('ALARM CLOCK: Snooze (%d)', get(obj, 'TasksExecuted')), ...
    'Okay (Stop)', ...
    'Okay (Stop)');
else
  btn = questdlg({datestr(now), msg}, ...
    sprintf('ALARM CLOCK: Snooze (%d)', get(obj, 'TasksExecuted')), ...
    'Okay (Stop)', ...
    sprintf('Snooze (%0.2g min)', get(obj, 'Period')/60), ...
    'Okay (Stop)');
end

% stop alarm sound
clear playsnd;

switch btn
  
  case 'Okay (Stop)'
    set(obj, 'TasksToExecute', get(obj, 'TasksExecuted'));
    
  otherwise
    % update the current time, so that snooze time starts NOW
    set(obj, 'Tag', datestr(now));
    
end

%--------------------------------------------------------------------------
% deleteAlarm
%--------------------------------------------------------------------------
function deleteAlarm(obj, edata) %#ok

wait(obj);
delete(obj);


%--------------------------------------------------------------------------
% findAlarm
%--------------------------------------------------------------------------
function findAlarm(action)

t = timerfindall('Name', 'Alarm Clock');
if isempty(t)
  fprintf('\nThere are no active alarms.\n\n');
else
  % delete ghost timers (timers that are not active)
  r = get(t, 'Running');
  notRunning = strmatch('off', r, 'exact');
  if ~isempty(notRunning)
    delete(t(notRunning));t(notRunning) = [];
  end
  
  if isempty(t)
    fprintf('\nThere are no active alarms.\n\n');
    return;
  end
  
  fprintf('\nThere are %d active alarms.\n\n', length(t));
  fprintf('Alarm #:  Status:    Time til next alarm:   Alarm message:\n');
  
  snoozeStatus = {'Pending', 'Snoozed'};
  for iTimer = 1:length(t)
    msg = t(iTimer).TimerFcn; msg = msg{2};
    if t(iTimer).TasksExecuted == 0
      alarmTime = t(iTimer).StartDelay;
      isSnooze  = 1;
      
    else
      alarmTime = t(iTimer).Period;
      isSnooze  = 2;
    end
    elapsedTime = etime(clock, datevec(t(iTimer).Tag));
    remainTime  = alarmTime - elapsedTime;
    if remainTime < 60
      rT  = remainTime;
      unt = 'sec';
      
    elseif remainTime < 3600
      rT  = remainTime / 60;
      unt = 'min';
      
    else
      rT  = remainTime / 3600;
      unt = 'hrs';
    end
    
    fprintf('%5d     %-11s%4.1f %-18s%s\n', iTimer, snoozeStatus{isSnooze}, rT, unt, msg);
  end
  fprintf('\n');
  
  if strcmpi(action, 'delete')
    s = input('Enter alarm number(s) to delete or <ENTER> leave untouched: ', 's');
    s = str2double(s);
    if ~isnan(s)
      try
        stop(t(s));
        % the timer object should automatically delete itself after stopping
      catch %#ok
      end
    end
  end
end

Contact us at files@mathworks.com