Prev: WM_CLICK
Next: MMControl
From: MikeD on
Neither sndPlaySound nor PlaySound (the preferred function to use) can play
midi files. They are for .wav files only. To play midi files, you can use
the mciSendString API function.

--
Mike
Microsoft MVP Visual Basic



"Martin Walke" <martin.walke_no_spam(a)vega_dot_co_dot_uk> wrote in message
news:OzL7xA8rFHA.2212(a)TK2MSFTNGP15.phx.gbl...
> Hi Rencie,
>
> Unless you want the user controls of the MMControl why not use the
> sndPlaySound API
>
> http://msdn.microsoft.com/library/default.asp?url=/library/en-us/multimed/htm/_win32_playsound.asp
>
>
> HTH
> Martin
>
> "Rencie" <Rencie(a)discussions.microsoft.com> wrote in message
> news:E0A3CA4C-E9BB-487B-8FA9-C31AAFAF2D63(a)microsoft.com...
>>I want to make a midi file play repeatedly, how do I achieve this in VB 6
>> using MMControl?
>
>


From: MikeD on

"Martin Walke" <martin.walke_no_spam(a)vega_dot_co_dot_uk> wrote in message
news:%237aC0B9rFHA.1028(a)TK2MSFTNGP10.phx.gbl...
>
> ret = sndPlaySound("c:\windows NT\media\flourish.mid", SND_ASYNC or
> SND_LOOP)

I suggest you actually try that code. It's not going to play the midi file.
It's going to play the system's default beep. sndPlaySound (nor PlaySound)
cannot be used to play midi files.

--
Mike
Microsoft MVP Visual Basic


From: Rencie on
Can you give an example for that in VB? Thank you.
From: Rencie on
I saw an example of mciSendString in the online library. In it, there's a
command button that I should press to make it start playing. I adopted it to
my form load and I removed the command button (to make it automatically
play), however, I can't seem to make it stop playing.

What can I do to make it stop playing?
What can I do repeat the song when it finishes?
From: MikeD on

"Rencie" <Rencie(a)discussions.microsoft.com> wrote in message
news:F471E378-4865-492F-8FC6-6C8C9E225082(a)microsoft.com...
>I saw an example of mciSendString in the online library. In it, there's a
> command button that I should press to make it start playing. I adopted it
> to
> my form load and I removed the command button (to make it automatically
> play), however, I can't seem to make it stop playing.


I could provide you with better examples if you had posted the code you're
using or had at least indicated what example you saw in the online library
(so I could see what that example code is).

>
> What can I do to make it stop playing?

Use the "stop" MCI command string. For example:

Call mciSendString("stop mymidi", vbNullString, 0&, 0&)

In the above, "mymidi" is an alias specified when the midi file is
"explicitly opened". However, MCI has an auto-open/close feature. It's
possible that instead of explicitly opening the midi file and specifying an
alias, you just used a command string like "play c:\myfolder\mymidi.mid". If
you had posted the code you're using, I could have tailored the above to how
you're doing things. Bottom line: Always post your code. <g>

> What can I do repeat the song when it finishes?

This is more difficult. MCI provides no mechanism for looping playback (as
the sndPlaySound and PlaySound functions do). You have to do it yourself.
The difficulty in this is knowing when playback has finished (so you'll know
to start it again). There are 2 ways you can do this (actually, there are
more than 2, but I'm only going to describe 2 and only provide code for 1).
One involves using a Timer control to constantly check the status of
playback The other involves using a callback procedure to receive a
notification from MCI (actually, Windows) when playback has ended. Using the
callback is the more efficient of the 2, but is also more difficult and
involved (especially if you aren't familiar with callbacks). Depending on
exactly what your program does, the Timer control way might be fine, so you
should try that first and test your app to make sure it doesn't interefere
with performance. For both of these, you must explicitly open the midi file
(IOW, you can't use the auto-open feature I mentioned earlier).

Here's an example using the Timer control method. Start a new Standard EXE
project and add a Timer control to Form1 and keep the default name of Timer1
for it. Add 2 command buttons and name them "cmdPlay" and "cmdStop" and
give each appropriate captions (for example, "Play" and "Stop"). Add a
checkbox and name it "chkLoop" and give it an appropriate caption ("Loop").
Copy and paste the following code into the form's General Declarations
section (certain lines might word-wrap so look out for that):


-----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 mciGetErrorString Lib "winmm.dll" Alias
"mciGetErrorStringA" (ByVal dwError As Long, ByVal lpstrBuffer As String,
ByVal uLength As Long) As Long

Private Declare Function GetWindowsDirectory Lib "kernel32" Alias
"GetWindowsDirectoryA" (ByVal lpBuffer As String, ByVal nSize 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 Const MAX_PATH As Long = 260

Private Sub DisplayMCIError(ByVal lErrorCode As Long)

Dim lRet As Long
Dim sBuffer As String * 255

Const BUFFERSIZE As Long = 255

lRet = mciGetErrorString(lErrorCode, sBuffer, BUFFERSIZE)

If lRet = 1 Then
MsgBox sBuffer, vbExclamation, "Midi Error"
Else
MsgBox "An unknown error occured", vbExclamation, "Error"
End If

Call mciSendString("close all", vbNullString, 0&, 0&)
Timer1.Enabled = False

cmdPlay.Enabled = True
cmdStop.Enabled = False

End Sub

Private Function GetShortFileName(ByVal sFileName As String) As String

Dim sBuffer As String

sBuffer = String$(MAX_PATH, vbNullChar)
Call GetShortPathName(sFileName, sBuffer, MAX_PATH)
GetShortFileName = Left$(sBuffer, InStr(1, sBuffer, vbNullChar,
vbTextCompare) - 1)

End Function

Private Function GetWinDir() As String

Dim sBuffer As String

sBuffer = String$(MAX_PATH, vbNullChar)
Call GetWindowsDirectory(sBuffer, MAX_PATH)
GetWinDir = Left$(sBuffer, InStr(1, sBuffer, vbNullChar,
vbTextCompare) - 1)

End Function

Private Sub LoopMidi(ByVal sFileName As String)

Dim lRet As Long

'Always get the short file name because MCI has problems with long file
names
sFileName = GetShortFileName(sFileName)

'Open the sequencer with the specified file.
lRet = mciSendString("open " & sFileName & " type sequencer alias Midi",
vbNullString, 0&, 0&)
If lRet <> 0 Then
DisplayMCIError lRet
Exit Sub
End If

'Change the enabled property of command buttons
cmdPlay.Enabled = False
cmdStop.Enabled = True

'Start playback
lRet = mciSendString("play Midi from 0", vbNullString, 0&, 0&)
If lRet <> 0 Then
DisplayMCIError lRet
Exit Sub
End If

'Setup the Timer control and enable it
Timer1.Interval = 1000
Timer1.Enabled = True

End Sub

Private Sub cmdPlay_Click()

Dim sWinDir As String

sWinDir = GetWinDir
If Right$(sWinDir, 1) <> "\" Then
sWinDir = sWinDir & "\"
End If

'Specify your own midi file. For testing, I recommend using
'a midi file of short duration so that you don't have to wait as
'long for it to finish in order to test the looping of it.
LoopMidi sWinDir & "media\flourish.mid"

End Sub

Private Sub cmdStop_Click()

Timer1.Enabled = False
Call mciSendString("close all", vbNullString, 0&, 0&)
cmdPlay.Enabled = True
cmdStop.Enabled = False

End Sub

Private Sub Form_Unload(Cancel As Integer)

'IMPORTANT: Be sure to close the midi sequencer device.
'Do not end the program from VB's menu or toolbar because
'the Unload event is not fired and the device may not get
'closed.

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

'Standard practice is to always disable Timer controls when
'the app is ending (or the form is closing).
Timer1.Enabled = False

End Sub

Private Sub Timer1_Timer()

Dim lRet As Long
Dim sBuffer As String * 255

Const BUFFERSIZE As Long = 255

'The Status command will return the status (playing, stopped, paused,
etc.)
lRet = mciSendString("status Midi mode", sBuffer, BUFFERSIZE, 0&)

If InStr(1, sBuffer, "stopped", vbTextCompare) Then
If chkLoop.Value = vbChecked Then
'Start playback again
lRet = mciSendString("play Midi from 0", vbNullString, 0&, 0&)
If lRet <> 0 Then
DisplayMCIError lRet
Exit Sub
End If
Else
Timer1.Enabled = False
lRet = mciSendString("close all", vbNullString, 0&, 0&)

cmdPlay.Enabled = True
cmdStop.Enabled = False
End If
End If

End Sub
-----END CODE

Try it this way first. If it causes problems with performance in your app,
post back and I'll provide code for using the callback procedure. Also note
that I did not fully test this code. It's quite possible (probable) there's
a bug or 2 in it. <g>


--
Mike
Microsoft MVP Visual Basic


First  |  Prev  |  Next  |  Last
Pages: 1 2 3 4
Prev: WM_CLICK
Next: MMControl