Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

Wave File

Posted on 2003-12-11
16
Medium Priority
?
412 Views
Last Modified: 2013-11-20
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
Comment
Question by:dani333
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 8
  • 5
  • 3
16 Comments
 
LVL 6

Expert Comment

by:GloomyFriar
ID: 9922363
SND_SYNC - Synchronous playback of a sound event. PlaySound returns after the sound event completes.
0
 
LVL 6

Expert Comment

by:GloomyFriar
ID: 9922393
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
 

Author Comment

by:dani333
ID: 9922436
How can i use SND_SYNC?
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 11

Expert Comment

by:KurtVon
ID: 9922455
if (PlaySound(0, NULL, SND_ASYNC | SND_NOSTOP | SND_NODEFAULT))
    // Sound complete
else
    // Sound still playing.

Hope this helps.
0
 

Author Comment

by:dani333
ID: 9922845
It doesn't work:-(
0
 
LVL 11

Expert Comment

by:KurtVon
ID: 9923515
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
 

Author Comment

by:dani333
ID: 9923699
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
 
LVL 11

Expert Comment

by:KurtVon
ID: 9924123
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
 

Author Comment

by:dani333
ID: 9925098
Ok,I will check it tomorrow, hope it will work and you will get
my points.

0
 
LVL 6

Expert Comment

by:GloomyFriar
ID: 9927227
>and you will get my points.
Don't forget, it's my idea.
0
 

Author Comment

by:dani333
ID: 9934727
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
 

Author Comment

by:dani333
ID: 9935815
Help me with that please...
0
 
LVL 6

Accepted Solution

by:
GloomyFriar earned 900 total points
ID: 9937362
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
 

Author Comment

by:dani333
ID: 9937513
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
 
LVL 6

Expert Comment

by:GloomyFriar
ID: 9940811
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
 

Author Comment

by:dani333
ID: 9941246
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.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction: Finishing the grid – keyboard support for arrow keys to manoeuvre, entering the numbers.  The PreTranslateMessage function is to be used to intercept and respond to keyboard events. Continuing from the fourth article about sudoku. …
Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Please read the paragraph below before following the instructions in the video — there are important caveats in the paragraph that I did not mention in the video. If your PaperPort 12 or PaperPort 14 is failing to start, or crashing, or hanging, …

609 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question