// tWave.h: CtWave class definition

/*
The idea of the CtWave class is that it holds wave data. It will load,
play and save any format but is currently only set to record in
PCM, mono, 8 kHz, 16 bits/sample (see the Record() member function).

To construct a CtWave class, use the constructor:

    CtWave  wav(this);

The optional first parameter to the constructor is the implementation
of the CtWaveSink class to send input and output completion
notifications to.

To load a wave file from the file system, use the Load() member function:

  wav.Load("chime.wav");

To save the currently held data into a file, use the Save() member function:

  wav.Save("mychime.wav");

To record new wave data (deallocating any currently held data),
use the Record() member function:

  wav.Record(WAVE_MAPPER, 60);

The first parameter is a low-level wave device identifier, e.g. as
returned from calling the TAPI function lineGetID(). The second parameter
is the maximum number of seconds to record. When the recording has
completed, the sink is called via OnWaveInData().

To play loaded or recorded data, use the Play() member function:

  wav.Play(WAVE_MAPPER);

The first parameter is a low-level wave identifier. When the wave
file has completed being played, the sink is called via OnWaveOutDone().

To stop wave data currently being played or recorded, use the Stop()
member function:

  wav.Stop();

To release the data currently being held by the wave object, use the
Close() member function:

  wav.Close();

Note: The Stop() and the Close() member functions are called implicitly
      when another action on the object requires it, e.g. when loading
      new wave data into an object that is currently being played.
*/

#ifndef TWAVE_H
#define TWAVE_H

#include <mmsystem.h>
#include "InvisibleWindow.h"

class CtWaveSink
{
public:
    // WaveOut events (playing)
    virtual void OnWaveOutOpen() {}
    virtual void OnWaveOutDone() {}
    virtual void OnWaveOutClose() {}

    // WaveIn events (recording)
    virtual void OnWaveInOpen() {}
    virtual void OnWaveInData() {}
    virtual void OnWaveInClose() {}
};

class CtWave : private InvisibleWindowSink
{
public:
    CtWave(CtWaveSink* pSink = 0);
    ~CtWave();

    // Load from a resource
    bool    Load(HINSTANCE hinst, UINT nID);
    bool    Load(HINSTANCE hinst, LPCTSTR pszID);

    // Load and save to/from a file
    bool    Load(LPCSTR pszFileName);
    bool    Save(LPCSTR pszFileName);

    // Sends OnWaveOutXxx() to sink as progress
    bool    Play(UINT nWaveOut, bool bLoop = false);

    // Sends OnWaveInXxx() to sink as progress
    bool    Record(UINT nWaveIn, UINT nSecs);

    bool    Stop();
    bool    Close();

protected:
    CtWaveSink*     m_pSink;
    WAVEHDR*        m_pWaveHdr;
    HPSTR           m_pData;
    DWORD           m_nRecordedSize;
    WAVEFORMATEX*   m_pFormat;
    DWORD           m_nFormatSize;
    HWAVEIN         m_hWaveIn;
    HWAVEOUT        m_hWaveOut;
    bool            m_bStopping;
    InvisibleWindow m_wnd;
    bool            m_bOwnData;

    bool    Load(HMMIO hmmio);

    // InvisibleWindowSink events
    LRESULT OnWindowMessage(HWND hwnd, UINT nMsg, WPARAM wparam, LPARAM lparam);
};

#pragma comment(lib, "winmm.lib")

#endif  // TWAVE_H
