[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

microsoft.public.vb.general.discussion

detect when media player is done playing sound file

Mike Scirocco

3/6/2012 7:34:00 PM

I play mp3s from a VB6 program using Media Player by adding a reference
to "Windows Media Player", on my XP system the file is here:
c:\windows\system32\msdxm.ocx.

I use this approach:

Dim Player As MediaPlayer.MediaPlayer
Set Player = New MediaPlayer.MediaPlayer
mp3file = "c:\full_path_to_file\sound.mp3"
Player.Open mp3file

I would like to stop the player and set the Player object to nothing
when the mp3 is finished playing before exiting the sub that contains
this code, as the program may have to play several different mp3s at
different times, but I don't know how to monitor the player state. I
tried using openstate and playstate like this:

Debug.Print Player.OpenState
Player.Open mp3file
Debug.Print Player.OpenState

Debug.Print Player.PlayState
Player.Open mp3file
Debug.Print Player.PlayState

but didn't see any changes. Is there a way to tell when the player is
done playing an mp3 so I can do the cleanup knowing the player is finished?

Mike
10 Answers

Mike Scirocco

3/6/2012 7:59:00 PM

0

On 3/6/2012 11:34 AM, Mike S wrote:
> I play mp3s from a VB6 program using Media Player by adding a reference
> to "Windows Media Player", on my XP system the file is here:
> c:\windows\system32\msdxm.ocx.
>
> I use this approach:
>
> Dim Player As MediaPlayer.MediaPlayer
> Set Player = New MediaPlayer.MediaPlayer
> mp3file = "c:\full_path_to_file\sound.mp3"
> Player.Open mp3file
>
> I would like to stop the player and set the Player object to nothing
> when the mp3 is finished playing before exiting the sub that contains
> this code, as the program may have to play several different mp3s at
> different times, but I don't know how to monitor the player state. I
> tried using openstate and playstate like this:
>
> Debug.Print Player.OpenState
> Player.Open mp3file
> Debug.Print Player.OpenState
>
> Debug.Print Player.PlayState
> Player.Open mp3file
> Debug.Print Player.PlayState
>
> but didn't see any changes. Is there a way to tell when the player is
> done playing an mp3 so I can do the cleanup knowing the player is finished?
>
> Mike

I may have found it, using notes found on this page:
http://www.bigresource.com/VB-MSDXM-OCX-Problem-Media-Player-Control--Hjryw...

This seems to work:

Set Player = New MediaPlayer.MediaPlayer
mp3file = "c:\full_path_to_file\sound.mp3"
Player.Open mp3file
Do Until Player.PlayState = mpStopped
DoEvents
Loop
Player.Stop
Set Player = Nothing

Mike

BeeJ

3/6/2012 10:32:00 PM

0

If I remember correctly, check the position vs the length.


Dee Earley

3/7/2012 9:16:00 AM

0

On 06/03/2012 19:34, Mike S wrote:
> I play mp3s from a VB6 program using Media Player by adding a reference
> to "Windows Media Player", on my XP system the file is here:
> c:\windows\system32\msdxm.ocx.
>
> I use this approach:
>
> Dim Player As MediaPlayer.MediaPlayer
> Set Player = New MediaPlayer.MediaPlayer
> mp3file = "c:\full_path_to_file\sound.mp3"
> Player.Open mp3file
>
> I would like to stop the player and set the Player object to nothing
> when the mp3 is finished playing before exiting the sub that contains
> this code, as the program may have to play several different mp3s at
> different times, but I don't know how to monitor the player state. I
> tried using openstate and playstate like this:
>
> Debug.Print Player.OpenState
> Player.Open mp3file
> Debug.Print Player.OpenState
>
> Debug.Print Player.PlayState
> Player.Open mp3file
> Debug.Print Player.PlayState
>
> but didn't see any changes. Is there a way to tell when the player is
> done playing an mp3 so I can do the cleanup knowing the player is finished?

You can use the normal events if you can make the reference public in a
class module or form with the WithEvents keyword and handle the
PlayStateChanged and/or EndOfStream events.

Of course, if you're using a wider scoped reference, then you can just
leave it hanging around and use it when you need it rather than creating
and destorying each time.

This also allows the playing to be asynchronous and not block until it's
finished (especially as .Open is asynchronous).

--
Deanna Earley (dee.earley@icode.co.uk)
i-Catcher Development Team
http://www.icode.co.uk...

iCode Systems

(Replies direct to my email address will be ignored.
Please reply to the group.)

Mike Scirocco

3/7/2012 11:20:00 PM

0

On 3/7/2012 1:16 AM, Deanna Earley wrote:
> On 06/03/2012 19:34, Mike S wrote:
>> I play mp3s from a VB6 program using Media Player by adding a reference
>> to "Windows Media Player", on my XP system the file is here:
>> c:\windows\system32\msdxm.ocx.
>>
>> I use this approach:
>>
>> Dim Player As MediaPlayer.MediaPlayer
>> Set Player = New MediaPlayer.MediaPlayer
>> mp3file = "c:\full_path_to_file\sound.mp3"
>> Player.Open mp3file
>>
>> I would like to stop the player and set the Player object to nothing
>> when the mp3 is finished playing before exiting the sub that contains
>> this code, as the program may have to play several different mp3s at
>> different times, but I don't know how to monitor the player state. I
>> tried using openstate and playstate like this:
>>
>> Debug.Print Player.OpenState
>> Player.Open mp3file
>> Debug.Print Player.OpenState
>>
>> Debug.Print Player.PlayState
>> Player.Open mp3file
>> Debug.Print Player.PlayState
>>
>> but didn't see any changes. Is there a way to tell when the player is
>> done playing an mp3 so I can do the cleanup knowing the player is
>> finished?
>
> You can use the normal events if you can make the reference public in a
> class module or form with the WithEvents keyword and handle the
> PlayStateChanged and/or EndOfStream events.
>
> Of course, if you're using a wider scoped reference, then you can just
> leave it hanging around and use it when you need it rather than creating
> and destorying each time.
>
> This also allows the playing to be asynchronous and not block until it's
> finished (especially as .Open is asynchronous).

Thanks for the ideas. I'll keep this for future use. Right now the code
approach is working:

Player.Open mp3file
Do Until Player.PlayState = mpStopped
DoEvents
Loop
Player.Stop
Set Player = Nothing

Thanks,
Mike

Larry Serflaten

3/8/2012 1:36:00 AM

0

Mike S wrote:

> Thanks for the ideas. I'll keep this for future use. Right now the code
> approach is working:
>
> Player.Open mp3file
> Do Until Player.PlayState = mpStopped
> DoEvents
> Loop
> Player.Stop
> Set Player = Nothing


Isn't that pegging the CPU meter? While the file plays, their
CPU will be running at 100%. You might want to check that.

Adding a Sleep command would greatly reduce the problem....

LFS

Dee Earley

3/8/2012 9:02:00 AM

0

On 07/03/2012 23:20, Mike S wrote:
> On 3/7/2012 1:16 AM, Deanna Earley wrote:
>> On 06/03/2012 19:34, Mike S wrote:
>>> I play mp3s from a VB6 program using Media Player by adding a reference
>>> to "Windows Media Player", on my XP system the file is here:
>>> c:\windows\system32\msdxm.ocx.
>>>
>>> I use this approach:
>>>
>>> Dim Player As MediaPlayer.MediaPlayer
>>> Set Player = New MediaPlayer.MediaPlayer
>>> mp3file = "c:\full_path_to_file\sound.mp3"
>>> Player.Open mp3file
>>>
>>> I would like to stop the player and set the Player object to nothing
>>> when the mp3 is finished playing before exiting the sub that contains
>>> this code, as the program may have to play several different mp3s at
>>> different times, but I don't know how to monitor the player state. I
>>> tried using openstate and playstate like this:
>>>
>>> Debug.Print Player.OpenState
>>> Player.Open mp3file
>>> Debug.Print Player.OpenState
>>>
>>> Debug.Print Player.PlayState
>>> Player.Open mp3file
>>> Debug.Print Player.PlayState
>>>
>>> but didn't see any changes. Is there a way to tell when the player is
>>> done playing an mp3 so I can do the cleanup knowing the player is
>>> finished?
>>
>> You can use the normal events if you can make the reference public in a
>> class module or form with the WithEvents keyword and handle the
>> PlayStateChanged and/or EndOfStream events.
>>
>> Of course, if you're using a wider scoped reference, then you can just
>> leave it hanging around and use it when you need it rather than creating
>> and destorying each time.
>>
>> This also allows the playing to be asynchronous and not block until it's
>> finished (especially as .Open is asynchronous).
>
> Thanks for the ideas. I'll keep this for future use. Right now the code
> approach is working:
>
> Player.Open mp3file
> Do Until Player.PlayState = mpStopped
> DoEvents
> Loop
> Player.Stop
> Set Player = Nothing

Be careful as this opens you up to rentrancy.
When you call Doevents, any clicks, timers, etc in the application can
be processed and trigger the same (or worse) code again.

--
Deanna Earley (dee.earley@icode.co.uk)
i-Catcher Development Team
http://www.icode.co.uk...

iCode Systems

(Replies direct to my email address will be ignored.
Please reply to the group.)

Mike Scirocco

3/8/2012 9:42:00 PM

0

On 3/7/2012 5:35 PM, Larry Serflaten wrote:
> Mike S wrote:
>> Thanks for the ideas. I'll keep this for future use. Right now the code
>> approach is working:
>> Player.Open mp3file
>> Do Until Player.PlayState = mpStopped
>> DoEvents
>> Loop
>> Player.Stop
>> Set Player = Nothing
> Isn't that pegging the CPU meter? While the file plays, their
> CPU will be running at 100%. You might want to check that.
> Adding a Sleep command would greatly reduce the problem....
> LFS

Larry,

It's a countdown timer used for people playing board games, run on a
laptop, they have 50 minutes to complete their game, and when it gets
down to 10, 5 or 0 minutes a sound file plays. If I use sleep then the
countdown stops while the alarm is playing. I had hoped that using an
asynchronous player wouldn't cause this problem, although I may be using
it incorrectly.

I was thinking that I could avoid this by writing another VB app that
plays the sound file, and then ends itself when the sound clip is done,
then I could use a sleep 1000 in the loop in that program. Do you have
any recommendations?

Mike

MikeD

3/8/2012 10:32:00 PM

0



"Mike S" <mscir@yahoo.com> wrote in message
news:jjb93i$oj$1@dont-email.me...
> On 3/7/2012 5:35 PM, Larry Serflaten wrote:
>> Mike S wrote:
>>> Thanks for the ideas. I'll keep this for future use. Right now the code
>>> approach is working:
>>> Player.Open mp3file
>>> Do Until Player.PlayState = mpStopped
>>> DoEvents
>>> Loop
>>> Player.Stop
>>> Set Player = Nothing
>> Isn't that pegging the CPU meter? While the file plays, their
>> CPU will be running at 100%. You might want to check that.
>> Adding a Sleep command would greatly reduce the problem....
>> LFS
>
> Larry,
>
> It's a countdown timer used for people playing board games, run on a
> laptop, they have 50 minutes to complete their game, and when it gets down
> to 10, 5 or 0 minutes a sound file plays. If I use sleep then the
> countdown stops while the alarm is playing. I had hoped that using an
> asynchronous player wouldn't cause this problem, although I may be using
> it incorrectly.
>


And you're using MediaPlayer for THAT? The MCI control included with VB
would be better, and it's a piece of crap IMO. <g> The biggest problem is
that you're making your app dependent on something that, yeah, will
*probably* exist, but by no means is guaranteed to exist. MediaPlayer CAN be
removed from systems. But besides that, for just simple playback of an MP3,
it's tremendous overkill and overhead.

Give this a try. Add this code to a new project that just has one form. Be
sure to fix line breaks and change the path and filename of what you want to
play.

-----BEGIN CODE
Option Explicit

Private Declare Function mciSendString Lib "winmm.dll" Alias
"mciSendStringA" (ByVal lpstrCommand As String, ByVal lpstrReturnString As
String, ByVal uReturnLength As Long, ByVal hwndCallback As Long) As Long

Private Declare Function GetShortPathName Lib "kernel32" Alias
"GetShortPathNameA" (ByVal lpszLongPath As String, ByVal lpszShortPath As
String, ByVal cchBuffer As Long) As Long
Private Function GetShortFileName(sFile As String) As String

Dim sBuffer As String
Dim lBytes As Long

sBuffer = String$(255, vbNullChar)
Call GetShortPathName(sFile, sBuffer, Len(sBuffer))

GetShortFileName = Left$(sBuffer, InStr(1, sBuffer, vbNullChar) - 1)

End Function

Private Sub Form_Click()

Dim sFileName As String

'Hard coded for example purposes only
sFileName = "H:\Media\Music\Rock\TED NUGENT - STRANGLEHOLD.MP3"

'Get the 8.3 form of this file because MCI has problems with
'long file names over a certain length, even if you embed
'quotation marks.
sFileName = GetShortFileName(sFileName)

Call mciSendString("play " & sFileName, vbNullString, 0&, 0&)

End Sub

Private Sub Form_Unload(Cancel As Integer)

Call mciSendString("close all", vbNullString, 0&, 0&)

End Sub

-----END CODE

If you want notification when playback stops, it's possible but a tad more
involved because you need to use subclassing to receive a message from MCI
(that's what the hwndCallback parameter is for in the mciSendString
function). Also note that using the above MCI command, the MCI device is
auto-opened and auto-closed. The only reason to explicitly close it in the
Unload event is because it will keep playing in the IDE until you close VB.
In a compiled app, this isn't an issue. But, it still shows how to close it
if you need to for any other reason (like if you have a Stop Playback
button).

Mike


Mike Scirocco

3/11/2012 8:59:00 AM

0

On 3/8/2012 2:31 PM, MikeD wrote:
>
>
> "Mike S" <mscir@yahoo.com> wrote in message
> news:jjb93i$oj$1@dont-email.me...
>> On 3/7/2012 5:35 PM, Larry Serflaten wrote:
>>> Mike S wrote:
>>>> Thanks for the ideas. I'll keep this for future use. Right now the code
>>>> approach is working:
>>>> Player.Open mp3file
>>>> Do Until Player.PlayState = mpStopped
>>>> DoEvents
>>>> Loop
>>>> Player.Stop
>>>> Set Player = Nothing
>>> Isn't that pegging the CPU meter? While the file plays, their
>>> CPU will be running at 100%. You might want to check that.
>>> Adding a Sleep command would greatly reduce the problem....
>>> LFS
>>
>> Larry,
>>
>> It's a countdown timer used for people playing board games, run on a
>> laptop, they have 50 minutes to complete their game, and when it gets
>> down to 10, 5 or 0 minutes a sound file plays. If I use sleep then the
>> countdown stops while the alarm is playing. I had hoped that using an
>> asynchronous player wouldn't cause this problem, although I may be
>> using it incorrectly.
>>
>
>
> And you're using MediaPlayer for THAT? The MCI control included with VB
> would be better, and it's a piece of crap IMO. <g> The biggest problem
> is that you're making your app dependent on something that, yeah, will
> *probably* exist, but by no means is guaranteed to exist. MediaPlayer
> CAN be removed from systems. But besides that, for just simple playback
> of an MP3, it's tremendous overkill and overhead.
>
> Give this a try. Add this code to a new project that just has one form.
> Be sure to fix line breaks and change the path and filename of what you
> want to play.
>
> -----BEGIN CODE
> Option Explicit
>
> Private Declare Function mciSendString Lib "winmm.dll" Alias
> "mciSendStringA" (ByVal lpstrCommand As String, ByVal lpstrReturnString
> As String, ByVal uReturnLength As Long, ByVal hwndCallback As Long) As Long
>
> Private Declare Function GetShortPathName Lib "kernel32" Alias
> "GetShortPathNameA" (ByVal lpszLongPath As String, ByVal lpszShortPath
> As String, ByVal cchBuffer As Long) As Long
> Private Function GetShortFileName(sFile As String) As String
>
> Dim sBuffer As String
> Dim lBytes As Long
>
> sBuffer = String$(255, vbNullChar)
> Call GetShortPathName(sFile, sBuffer, Len(sBuffer))
>
> GetShortFileName = Left$(sBuffer, InStr(1, sBuffer, vbNullChar) - 1)
>
> End Function
>
> Private Sub Form_Click()
>
> Dim sFileName As String
>
> 'Hard coded for example purposes only
> sFileName = "H:\Media\Music\Rock\TED NUGENT - STRANGLEHOLD.MP3"
>
> 'Get the 8.3 form of this file because MCI has problems with
> 'long file names over a certain length, even if you embed
> 'quotation marks.
> sFileName = GetShortFileName(sFileName)
>
> Call mciSendString("play " & sFileName, vbNullString, 0&, 0&)
>
> End Sub
>
> Private Sub Form_Unload(Cancel As Integer)
>
> Call mciSendString("close all", vbNullString, 0&, 0&)
>
> End Sub
>
> -----END CODE
>
> If you want notification when playback stops, it's possible but a tad
> more involved because you need to use subclassing to receive a message
> from MCI (that's what the hwndCallback parameter is for in the
> mciSendString function). Also note that using the above MCI command, the
> MCI device is auto-opened and auto-closed. The only reason to explicitly
> close it in the Unload event is because it will keep playing in the IDE
> until you close VB. In a compiled app, this isn't an issue. But, it
> still shows how to close it if you need to for any other reason (like if
> you have a Stop Playback button).
>
> Mike

Thanks Mike, this will work great.

Mike S

MikeD

3/11/2012 11:38:00 PM

0



"Mike S" <mscir@yahoo.com> wrote in message
news:jjhphg$s28$1@dont-email.me...
>
> Thanks Mike, this will work great.
>


Glad I could help. And you've eliminated a dependency that you really didn't
need to have.

Mike