Link to home
Start Free TrialLog in
Avatar of dani333
dani333

asked on

Wave File

Hi,
I have used PlaySound function,and i need to know when the wave file stop playing, in order to do some action while it's playing.
I used :
PlaySound(pszSound, NULL, SND_ASYNC | SND_FILENAME);
Then i have :
while( IsPlaying() )//somthing like that.
   {
     ...      

   }
How can i know if the wave file is still playing and when it stops?

Thanks a lot.

Dani.
Avatar of GloomyFriar
GloomyFriar

SND_SYNC - Synchronous playback of a sound event. PlaySound returns after the sound event completes.
You can run the PlaySound() with the  SND_SYNC flag in a separate thread.
And then you can use WaitForSingleObject to define is the thread still running(playing) or not.
Avatar of dani333

ASKER

How can i use SND_SYNC?
if (PlaySound(0, NULL, SND_ASYNC | SND_NOSTOP | SND_NODEFAULT))
    // Sound complete
else
    // Sound still playing.

Hope this helps.
Avatar of dani333

ASKER

It doesn't work:-(
Hmm, odd.  Does the request reset the sound device?

If you know the length of the sound file you could use waveOutGetPosition or the waveOutProc to catch the callback when if finishes.  I'm not sure if the callback will get called for PlaySound, though.  It is considered a wave library function, so it might get the WOM_DONE message.

Of course, the solution GloomyFriar offered of doing a synchronous playback in another thread might be  simpler solution.

Hope this helps.
Avatar of dani333

ASKER

I don't know how to use WaitForSingleObject() function and i'm not so good with threads
Can u help me with that please?

Thanks.
Well, personally I don't think you want to use WaitForSingleObject simply because you don't want to wait, you want to process during playback or you would have used SND_SYNC.

The easiest way to do the threading is in the object that plays the sound, be it a dialog, window, or whatever.  I'll pretend it is CSoundObject.  First add the following members:

class CSoundObject
{
  ...
public:
    void StartSound(const CString& strSoundName);
    void PlayTheSound();

private:
    CString m_strSound;
    bool m_bPlaying;
    CCriticalSection m_cPlayCritical;

    static void CallPlay(void *pData);
};


Then write the functions as

bool CSoundObject::StartSound(const CString& strSoundName)
{
    m_cPlayCritical.Lock();
    if (!m_bPlaying)
    {
        m_cPlayCritical.Unlock();
        m_strSound = strSoundName
        m_bPlaying = true;
        _beginthread(CallPlay, 0, (void*)(this));
    }
    else
        m_cPlayCritical.Unlock();

    return m_bPlaying;
}

void CSoundObject::CallPlay(void *pData)
{
     ((CSoundObject*)pData)->PlayTheSound();
    _endthread();
}

void CSoundObject::PlayTheSound()
{
    m_cPlayCritical.Lock();
    if (!m_bPlaying)
    {
        m_cPlayCritical.Unlock();
        PlaySound(m_strSound, NULL, SND_SYNC);
        m_cPlayCritical.Lock();
        m_bPlaying = false;
    }
    m_cPlayCritical.Unlock();
}


Then just call StartSound with the name of your sound and check m_bPlaying to see if the thread is still active.  Be sure to put checks in a critical section, though I'm not sure it makes a difference for something like checking a bool, it never hurts.

Hope this helps.

Avatar of dani333

ASKER

Ok,I will check it tomorrow, hope it will work and you will get
my points.

>and you will get my points.
Don't forget, it's my idea.
Avatar of dani333

ASKER

Hi again,
I did what u told me with the thread and stuff but i still can't do other operation while the wave file is playing.
I want to do it in the function OnInitDialog() ,the program is stuck in the StartSound line
until the wave file is finished,so what should i do,where should i check the flag?

Thanks again.
Avatar of dani333

ASKER

Help me with that please...
ASKER CERTIFIED SOLUTION
Avatar of GloomyFriar
GloomyFriar

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of dani333

ASKER

Hi GloomyFriar,
Sorry to disturb you again hope u will understand my problem now.
This is what i have made:

BOOL CPlayerDlg::OnInitDialog()
{
      CDialog::OnInitDialog();

 .
 .
 .
       

    PlayStartSound(".\\wav\\start1.wav");

return TRUE;  
}
 How can I check if IsPlaying() automaticly after the OnInitDialog() finished and already start
playing?
I don't have main or somthing,the wave file start playing in the OnInitDialog(), i can't do the for loop in this function it won't work,where can i put it ?

Thanks again.
I can't understand what you want to make.
You can use player.IsPlaing() anywhere in you programm.
One hint. Create the player like this:
KPlayer *pPlayer(FileName);
and don't forget to destroy it like this:
delete pPlayer.

One addition to the code:
KPlayer::~KPlayer(void)
{
  if (WAIT_OBJECT_0 != WaitForSingleObject(m_hThread, 0))
  {
    TerminateThread(m_hThread, -1);
  }
}

Do you want to know, when the playing stopped?
Then you can do like the following:
DWORD WINAPI KPlayer::PlayThreadFunc(LPVOID lpParameter)
{
  KPlayer *pPlayerObj = (KPlayer *)lpParameter;
  PlaySound(pPlayerObj->m_FileName, NULL, SND_SYNC);

  /*
   * You can use PostThreadMessage, if you want.
   * To get window handle you can use AfxGetMainWnd( );
   * or just pass it to KPlayer constructor like this:
   * KPlayer::KPlayer(char *FileName, HWND hWnd);
   * {
   *   ...
   *   m_hWnd = hWnd;
   * }
   */
  PostMessage(m_hWnd, WM_USER + 100, 0, 0);
  return 0;
}
Avatar of dani333

ASKER

I put PlayStartSound() in the constructor and IsPlaying in OnPaint().

Thanks for your help.