From: mick on
Is there any way to detect when a soundplayer (playing asynchronously)
has finished playing a sound?

mick

From: Peter Duniho on
mick wrote:
> Is there any way to detect when a soundplayer (playing asynchronously)
> has finished playing a sound?

I assume you're talking about System.Media.SoundPlayer? AFAIK, no.
But, you can play the sound synchronously in a thread you have control
over and detect the end of the sound that way. For example:

SoundPlayer player = �;

Action<SoundPlayer> play = p =>
{
p.PlaySync();
MethodToCallWhenSoundIsDone();
};

play.BeginInvoke(player);

The above creates a delegate instance from an anonymous method that
calls PlaySync() and then calls a method when it's done. Then the
Action<SoundPlayer>.BeginInvoke() method causes the delegate instance to
be invoked on a thread pool thread asynchronously.

Of course, you can implement the threading aspect in any way you like;
you could even create a new class that inherits or composites the
SoundPlayer class and which adds a new event (e.g. "PlayCompleted") that
is raised when the synchronous-play-wrapped-in-a-thread finishes.

Pete
From: mick on


"Peter Duniho" <NpOeStPeAdM(a)NnOwSlPiAnMk.com> wrote in message
news:AqydnfpNSvI6_YPRnZ2dnUVZ_qmdnZ2d(a)posted.palinacquisition...
> mick wrote:
>> Is there any way to detect when a soundplayer (playing asynchronously)
>> has finished playing a sound?
>
> I assume you're talking about System.Media.SoundPlayer? AFAIK, no. But,
> you can play the sound synchronously in a thread you have control over and
> detect the end of the sound that way. For example:
>
> SoundPlayer player = �;
>
> Action<SoundPlayer> play = p =>
> {
> p.PlaySync();
> MethodToCallWhenSoundIsDone();
> };
>
> play.BeginInvoke(player);
>
> The above creates a delegate instance from an anonymous method that calls
> PlaySync() and then calls a method when it's done. Then the
> Action<SoundPlayer>.BeginInvoke() method causes the delegate instance to
> be invoked on a thread pool thread asynchronously.
>
> Of course, you can implement the threading aspect in any way you like; you
> could even create a new class that inherits or composites the SoundPlayer
> class and which adds a new event (e.g. "PlayCompleted") that is raised
> when the synchronous-play-wrapped-in-a-thread finishes.
>
> Pete

Thanks Pete. Yes I ended up trying something similar except I used a Task
(as
I`m reading a book about the TPL). The problem I found was that I couldnt
stop the sound. The SoundPlayer.Stop() method only seems to work on the
thread
that started it. The scenario is as follows -

I have a "Play" button which when pressed changes to a "Stop" button (I just
change the
button text property depending on what is happening) and then starts the
sound
playing. Then there are two scenarios -

1. The user presses the button again to stop the sound when the button text
is
changed back to "Play" and the sound stops.
2. The sound plays till the end and then the button text changes back to
"Play".

The problem of course if you start and stop the the player on the main
thread is
you cant detect when user doesnt actually stop the sound but lets it play to
the
end - the button text is still stuck on "Stop".

I got round it by using the mciSendString() command from winmm.dll to find
the
length of the sound then set a Timer going that will wait for that amount of
time
then in its Tick event changes the button text back to Play. I'd never
heard of the
mci stuff until Googling around today.

It works quite nicely but I always feel there's a better way:-)

mick

From: mick on


"mick" <coughcough(a)privacy.com> wrote in message
news:udKLDHMELHA.1996(a)TK2MSFTNGP06.phx.gbl...
> The problem of course if you start and stop the the player on the main
> thread is you cant detect when user doesnt actually stop the sound but
> lets it play to the end.

Should have said using the asynchronous Play.

mick