function audioShow(filename)
% audioShow Select a part of audio file and right click to play.
% 
% 	Once it is active the mouse position is constantly tracked and printed 
%   on the figure title. Draging mouse while pressing the mouse left button
% 	will select the region to play. Clicking the mouse right button will
%   play the selected part of audio file.
% 
% Usage
% 	audioShow(filename) plot the specified audio file and play the selected
% 	region.
%
% July, 2008, Keshi Dai
%
% Credits
%   GTRACK - Jose F. Pina, Portugal
%   http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=15099
%


% default format for printing coordinates in title
titleXFmt = '%d';
titleYFmt = '%3.3f';
if nargin < 1 
    filename = 'SI492';
end

[timitData, timitFs, timitHead] = TIMITread(filename);
figure;
plot(timitData);
set(gcf,'doublebuffer','on');
set(gca, 'XLim', [0, length(timitData)]);
%set(gca, 'YLim', [min(timitData)*2.8, max(timitData)*2.8]);
set(gca, 'NextPlot','add');
set(gca,'XLimMode','manual'); 
set(gca,'YLimMode','manual'); 
hold on;

% get current figure event functions
currFcn = get(gcf, 'windowbuttonmotionfcn');
currFcn2 = get(gcf, 'windowbuttondownfcn');
currTitle = get(get(gca, 'Title'), 'String');

% add data to figure handles
handles = guidata(gca);
if (isfield(handles,'ID') & handles.ID==1)
	disp('audioShow is already active.');
	return;
else
	handles.ID = 1;
end
handles.currFcn = currFcn;
handles.currFcn2 = currFcn2;
handles.currTitle = currTitle;
handles.theState = uisuspend(gcf);
guidata(gca, handles);

% set event functions 
set(gcf,'Pointer','ibeam');  
set(gcf, 'windowbuttonmotionfcn', @audioShow_OnMouseMove);
set(gcf, 'windowbuttondownfcn', @audioShow_OnMouseDown);
set(gcf, 'windowbuttonupfcn', @audioShow_OnMouseUp);

% declare variables
xStartInd = 0;
yStartInd = 0;
xMoveInd = 0;
yMoveInd = 0;
xEndInd = 0;
yEndInd = 0;
clickData = [];	
h=NaN;

%if need to refresh
inSelection = false;
isSelected = false;

% set output mode
if nargout,	
	uiMode = 'uiwait';		% use UIWAIT and return to clickData
	uiwait;
else
	uiMode = 'noreturn';	% dont't use UIWAIT and don't return results (print only)
end


%% --- nested functions ---------------------------------------------------

%% mouse move callback
function audioShow_OnMouseMove(src,evnt)
    % get mouse position
    pt = get(gca, 'CurrentPoint');
    xMoveInd = round(pt(1, 1));
    yMoveInd = pt(1, 2); 

    % check if its within axes limits
    xLim = get(gca, 'XLim');	
    yLim = get(gca, 'YLim');
    if xMoveInd < xLim(1) | xMoveInd > xLim(2)
        title('Out of X limit');	
        return;
    end
    if yMoveInd < yLim(1) | yMoveInd > yLim(2)
        title('Out of Y limit');
        return;
    end

    % update figure title
    if ~isSelected
        try
            title(['X = ' num2str(xMoveInd,titleXFmt) ', Y = ' num2str(yMoveInd,titleYFmt)]);
        % possibility of wrong format strings...
        catch
            audioShow_Off()
            error('audioShow: Error printing coordinates. Check that you used a valid format string.')
        end
    end
end

%% mouse move callback
function audioShow_OnMouseSelectMove(src,evnt)
    % get mouse position
    pt = get(gca, 'CurrentPoint');
    xMoveInd = round(pt(1, 1));
    yMoveInd = pt(1, 2); 

    % check if its within axes limits
    xLim = get(gca, 'XLim');	
    yLim = get(gca, 'YLim');
    if xMoveInd < xLim(1) | xMoveInd > xLim(2)
        title('Out of X limit');	
        return;
    end
    if yMoveInd < yLim(1) | yMoveInd > yLim(2)
        title('Out of Y limit');
        return;
    end

    if inSelection
        if strcmp(get(gcf,'SelectionType'),'normal')
            %patch([xStartInd, xStartInd, xMoveInd, xMoveInd],[yLim(1) yLim(2) yLim(2) yLim(1)],...
            %    'r', 'facecolor',[.7 .7 .7], 'facealpha',0.7)
            set(h, 'XData', [xStartInd xStartInd  xMoveInd xMoveInd]);
            set(h, 'YData', [yLim(1) yLim(2) yLim(2) yLim(1)]);
        end
        % update figure title
        try
            title(['X = ' num2str(xMoveInd,titleXFmt) ', y = ' num2str(yMoveInd,titleYFmt)]);
        % possibility of wrong format strings...
        catch
            audioShow_Off()
            error('audioShow: Error printing coordinates. Check that you used a valid format string.')
        end
    end
end

%% mouse click down callback
function audioShow_OnMouseDown(src,evnt)
    % if right button, terminate
    if strcmp(get(gcf,'SelectionType'),'alt')
        %audioShow_Off
        if isSelected
            if(xStartInd>xEndInd)
                temp = xStartInd;
                xStartInd = xEndInd;
                xEndInd = temp;
            end
            play(timitData(xStartInd:xEndInd), timitFs);
        end
        return
    end
    
    % get mouse position
    pt = get(gca, 'CurrentPoint');
    xMoveInd = round(pt(1, 1)); 
    yMoveInd = pt(1, 2); 
    xStartInd = xMoveInd;
    yStartInd = yMoveInd;
    % print the start point
    %fprintf('X = %d   Y = %f\n',xStartInd,yStartInd);

    if ~isnan(h)
        delete(h);
    end
    h=patch([xStartInd xStartInd  xStartInd xStartInd],[yStartInd yStartInd yStartInd yStartInd], ...
             'r', 'facecolor',[.75 .75 .75], 'facealpha', 0.7, 'EdgeColor', 'none', 'EraseMode', 'xor');
    inSelection = true;
    isSelected = false;
    set(gcf, 'windowbuttonmotionfcn', @audioShow_OnMouseSelectMove); 
end

%% mouse click up callback
function audioShow_OnMouseUp(src,evnt)
    % else add click to clickData
    xEndInd = xMoveInd;
    yEndInd = yMoveInd;
    
    if xStartInd == xEndInd && yStartInd == yEndInd
        inSelection = false;
        isSelected = false;
        set(gcf, 'WindowButtonMotionFcn', @audioShow_OnMouseMove);
        title(['X = ' num2str(xEndInd,titleXFmt) ', Y = ' num2str(yEndInd,titleYFmt)]);
    end
    
    if inSelection
        inSelection = false;
        if ~isSelected
            isSelected = true;
            set(gcf, 'WindowButtonMotionFcn', '');
            title(['X = ' num2str(xStartInd,titleXFmt) ' : ' num2str(xEndInd,titleXFmt)]);
        else
            isSelected = false;
            set(gcf, 'WindowButtonMotionFcn', @audioShow_OnMouseMove);
            title(['X = ' num2str(xEndInd,titleXFmt) ', Y = ' num2str(yEndInd,titleYFmt)]);
        end
    end
    %fprintf('X = %d   Y = %f\n',xEndInd,yEndInd);
end


%% terminate callback
function audioShow_Off(src,evnt)
    % restore default figure properties
    handles = guidata(gca);
    set(gcf, 'windowbuttonmotionfcn', handles.currFcn);
    set(gcf, 'windowbuttondownfcn', handles.currFcn2);
    set(gcf,'Pointer','arrow');;
    title(handles.currTitle);
    uirestore(handles.theState);
    handles.ID=0;
    guidata(gca,handles);

    % if there are outputs to assign do so
    switch uiMode
        case 'uiwait'	% data return as output argument (clickData)
            varargout{1} = clickData;
            uiresume,
        case 'nowait'	% data assigned in base workspace as new variable
            assignin('base',newVarName,clickData);
            fprintf('Variable %s assigned with click data.\n',newVarName);
        case 'noreturn'
            % nothing to return
    end
end

%% --- end nested functions -----------------------------------------------

end % end everything