function presentation_timer
% Counts down minutes and seconds for presentation period in black text.
% Counts down minutes and seconds for question period in red text.
% Makes audible warnings at specified times.
% Displays stop message and audible warnings.
%
% By Geoffrey Stewart Morrison http://geoff-morrison.net/
% Release 2012-12-02
%
% COMMANDS:
% {[spacebar],[primary mouse click]}: start/stop
% {[delete],[backspace],[secondary mouse click]}: reset
% [enter]: reset and start

% SETTINGS:
present_mins = 15;          % number of minutes for presentation
present_secs = 00;          % number of additioanl seconds for presentation
present_dings = [5*60 60];  % vector of times remaining in presentation (in seconds) when an audible warning will be made (set to "[0]" for no dings)
quest_mins = 05;            % number of minutes for questions
quest_secs = 00;            % number of additional seconds for questions
quest_dings = [60];         % vector of times remaining in questions (in seconds) when an audible warning will be made (set to "[0]" for no dings)
stop_message = 'STOP';      % stop message
size_mmss = 0.4;            % size of display text for minutes and seconds relative to window height
size_message = 0.4;         % size of display text for stop message relative to window height
full_screen = true;         % set "true" for full screen display, "false" for a small window (10% of screen size)

% % Uncomment the following lines for a short demo
% present_mins = 0;
% present_secs = 10;
% present_dings = [6 3];
% quest_mins = 0;
% quest_secs = 5;
% quest_dings = [0];




% start by using settings for presentation period
mmss_str = [num2str(present_mins, '%02.00f'), ':', num2str(present_secs, '%02.00f')];
present_secs_total = present_mins * 60 + present_secs;
secs_remaining = present_secs_total;
ding_times = present_dings;
present = true;

% question-period duration in seconds
quest_secs_total = quest_mins * 60 + quest_secs;


% window size calculations
screen_size = get(0,'screensize');
screen_width = screen_size(3) - screen_size(1);
screen_height = screen_size(4) - screen_size(2);

if ~full_screen % small screen in bottom right corner
    screen_width = screen_width * 0.1;
    screen_height = screen_height * 0.1;
    screen_size(1) = screen_size(3) - screen_width;
    screen_size(3) = screen_width;
    screen_size(4) = screen_height;
end

window_pos = [screen_width * 0.025,...
    screen_height * 0.05,...
    screen_width * 0.95,...
    screen_height * 0.9];


% make figure and display area
figure('numbertitle','off', 'name','Presentation Timer',...
    'color',[.5 .5 .5], 'menubar','none', 'toolbar','none',...
    'pos',screen_size, 'closerequestfcn',@cleanup);

axis off

display_gui = uicontrol('style','edit', 'string',mmss_str,...
    'units','pixels', 'position',window_pos, 'fontsize',screen_height*size_mmss,...
    'foregroundcolor','k', 'backgroundcolor',[.9 .9 .9]);


% establish timer
timer_object = timer('timerfcn',@update_display, 'period',1, 'executionmode','fixedrate');
closed = false;


% get user input and respond accordingly
paused = true;
keypress = 0;
while keypress ~= 27 % [escape]
    
    try
        [~, ~, keypress] = ginput(1);
    catch
        keypress = 27;
    end
    
    if isempty(keypress) % [enter]: reset and start
        if ~paused
            stop(timer_object);
            paused = true;
        end
        mmss_str = [num2str(present_mins, '%02.00f'), ':', num2str(present_secs, '%02.00f')];
        secs_remaining = present_secs_total;
        ding_times = present_dings;
        present = true;
        set(display_gui, 'string',mmss_str, 'foregroundcolor','k');
        if paused
            start(timer_object);
        end
        paused = false;
        keypress = 0;
        
    else
        switch keypress
            
            case {32 1} % {[spacebar],[primary mouse click]}: start/stop
                if paused
                    start(timer_object);
                    paused = false;
                else
                    stop(timer_object);
                    paused = true;
                end
                
            case {127 8 3} % {[delete],[backspace],[secondary mouse click]}: reset
                if ~paused
                    stop(timer_object);
                end
                mmss_str = [num2str(present_mins, '%02.00f'), ':', num2str(present_secs, '%02.00f')];
                secs_remaining = present_secs_total;
                ding_times = present_dings;
                present = true;
                set(display_gui, 'string',mmss_str, 'foregroundcolor','k');
                paused = true;
        end
    end
    
end

% cleanup
if ~closed
    cleanup
end


return


    % update time-displayed function
    function update_display(varargin)
        
        % calculate remaining time
        secs_remaining = secs_remaining - 1;
        
        if secs_remaining < 1 && ~present % display stop mesage
            set(display_gui, 'string',stop_message, 'fontsize',screen_height*size_message);
            if get(display_gui,'foregroundcolor') == [1 0 0]; % red
                new_color = 'y';
            else
                new_color = 'r';
            end
            set(display_gui, 'foregroundcolor',new_color);
            beep
            
        else
            
            if secs_remaining < 1 && present % switch to question period
                mmss_str = [num2str(quest_mins, '%02.00f'), ':', num2str(quest_secs, '%02.00f')];
                secs_remaining = quest_secs_total;
                ding_times = quest_dings;
                present = false;
                set(display_gui, 'string',mmss_str, 'foregroundcolor','r');
                beep
                
            else % update time display
                mm = floor(secs_remaining/60);
                ss = rem(secs_remaining, 60);
                mmss_str = [num2str(mm, '%02.00f'), ':', num2str(ss, '%02.00f')];
                set(display_gui, 'string',mmss_str);
                
            end
            
            if ~isempty(find(secs_remaining == ding_times, 1)) % audible warning
                beep
            end
                       
        end
    end

    % cleanup function
    function cleanup(varargin)
        stop(timer_object);
        delete(timer_object);
        closereq;
        closed = true;
    end


end
