Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 414
  • Last Modified:

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.
0
dani333
Asked:
dani333
  • 8
  • 5
  • 3
1 Solution
 
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
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
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
 
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

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

  • 8
  • 5
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now