// tDialString.cpp

//#include "stdafx.h"
#include "tDialString.h"

bool CtDialString::Dial(UINT nWaveOut, UINT nDigitDuration, UINT nCommaDelay)
{
    // Make sure we're stopped
    Cancel();

    // Cache the settings and dial the first digit
    m_nWaveOut = nWaveOut;
    m_nDigitDuration = nDigitDuration;
    m_nCommaDelay = nCommaDelay;
    m_nIndex = 0;

    return PlayDigit();
}

void CtDialString::Cancel()
{
    // Stop the wave and the timer
    if( m_state != dsStopped )
    {
        m_dtmf.Stop();
        m_timer.Stop();
        m_state = dsStopped;

        // Notify sink the digits have been dialed
        if( m_pSink ) m_pSink->OnDialDone();
    }
}

void CtDialString::OnTimer()
{
    switch( m_state )
    {
    // If it's the wave file, stop it and wait for
    // it to stop before playing the next digit
    case dsPlaying:
        m_dtmf.Stop();
    break;

    // If it's a pause, stop the timer and play the next digit
    case dsPausing:
        m_timer.Stop();
        m_nIndex++;
        if( !PlayDigit() && m_pSink ) m_pSink->OnDialError();
    break;

    // If it's stopped, don't do anything
    case dsStopped:
    break;

    default:
        assert(false && "Unknown state");
    break;
    }
}

bool CtDialString::PlayDigit()
{
    // While there are digits left, dial the next one
    while( m_nIndex < m_sDigits.length() )
    {
        char digit = m_sDigits[m_nIndex];

        switch( digit )
        {
        // Start a timer for the length of the delay
        case ',': // pause
        case 'W': // wait for dialtone
        case 'w': // wait for dialtone
            m_state = dsPausing;
            return m_timer.Start(m_nCommaDelay);
        break;

        // 0-9, A-D, #, *
        default:
            if( m_dtmf.SetTone(digit) )
            {
                if( m_dtmf.Play(m_nWaveOut, true) )
                {
                    m_state = dsPlaying;
                    return true;
                }
                else
                {
#ifdef _DEBUG
                    char    sz[256];
                    wsprintf(sz, "Can't play digit= '%c'\n", digit);
                    OutputDebugString(sz);
#endif
                    return false;
                }
            }
        break;
        }

        // If we get here, we hit an illegial DTMF,
        // e.g. dash, space, parens, so ignore it
        m_nIndex++;
    }

    // If there are no digits left, we're done
    m_state = dsStopped;

    // Notify sink the digits have been dialed
    if( m_pSink ) m_pSink->OnDialDone();

    return true;
}

void CtDialString::OnWaveOutOpen()
{
    // Start the timer
    m_timer.Start(m_nDigitDuration);
}

void CtDialString::OnWaveOutDone()
{
    switch( m_state )
    {
    // Pause between digits
    case dsPlaying:
        m_state = dsPausing;
        m_timer.Start(INTERDIGIT_DELAY);
    break;

    // Do nothing as the sink has been notified in Cancel()
    case dsStopped:
    break;

    // Not supposed to happen
    case dsPausing:
    default:
        assert(false && "Invalid state");
    break;
    }
}
