From: MikeD on 2 Sep 2005 13:24 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 2 Sep 2005 13:34 "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 2 Sep 2005 18:31 Can you give an example for that in VB? Thank you.
From: Rencie on 2 Sep 2005 20:51 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 3 Sep 2005 00:01
"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 |