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.
dani333Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

GloomyFriarCommented:
SND_SYNC - Synchronous playback of a sound event. PlaySound returns after the sound event completes.
0
GloomyFriarCommented:
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.
0
dani333Author Commented:
How can i use SND_SYNC?
0
Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

KurtVonCommented:
if (PlaySound(0, NULL, SND_ASYNC | SND_NOSTOP | SND_NODEFAULT))
    // Sound complete
else
    // Sound still playing.

Hope this helps.
0
dani333Author Commented:
It doesn't work:-(
0
KurtVonCommented:
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.
0
dani333Author Commented:
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.
0
KurtVonCommented:
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.

0
dani333Author Commented:
Ok,I will check it tomorrow, hope it will work and you will get
my points.

0
GloomyFriarCommented:
>and you will get my points.
Don't forget, it's my idea.
0
dani333Author Commented:
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.
0
dani333Author Commented:
Help me with that please...
0
GloomyFriarCommented:
The working code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>

class KPlayer
{
public:
   KPlayer(char *FileName);
   BOOL IsPlaing(void);

private:
   HANDLE m_hThread;
   DWORD m_idThread;
   char m_FileName[_MAX_PATH + 1];
   static DWORD WINAPI PlayThreadFunc(LPVOID lpParameter);
};

KPlayer::KPlayer(char *FileName)
{
  strcpy(m_FileName, FileName);
  m_hThread = CreateThread(NULL, 0, PlayThreadFunc, this, 0, &m_idThread);
  if (NULL == m_hThread)
  {
    printf("ERROR: Can't create thread [%d]", GetLastError());
  }
}

BOOL KPlayer::IsPlaing(void)
{
  if (WAIT_TIMEOUT == WaitForSingleObject(m_hThread, 0))
  {
    return TRUE;
  }
  else
  {
    return FALSE;
  }
}

DWORD WINAPI KPlayer::PlayThreadFunc(LPVOID lpParameter)
{
  KPlayer *pPlayerObj = (KPlayer *)lpParameter;
  PlaySound(pPlayerObj->m_FileName, NULL, SND_SYNC);
  return 0;
}

int main(int argc, char **argv)
{
  if (argc < 2)
  {
    printf("\nUsage: %s FileName\n", argv[0]);
    exit(-1);
  }

  KPlayer player(argv[1]);

  for (int i=0; i<1000; i++)
  {
    if (player.IsPlaing())
    {
      printf("Still playing...\n");
    }
    else
    {
      printf("Play stopped.\n");
    }
   
    Sleep(15);
  }

  return 0;
}
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
dani333Author Commented:
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.
0
GloomyFriarCommented:
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;
}
0
dani333Author Commented:
I put PlayStartSound() in the constructor and IsPlaying in OnPaint().

Thanks for your help.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
System Programming

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.