MCI (Media Control Interface) provides a high-level interface to play multimedia files (or "device elements" as defined in MCI). By default, MCI WAVE/AVI drivers (MCIAVI and MCIWAVE) use mmioOpen to open a file stored on a disk. If the file name contains a "+" character, mmioOpen will look for a custom procedure as identified by the three-character file extension to handle the reading and writing of a file. This technique can be applied to allow MCI to play WAVE/AVI files that are already loaded into memory.
The following steps demonstrate this approach. We use "MEY" as the file extension in this example:
1. Install a custom MMIO procedure as follows: |
Where MEY = mmioFOURCC('M', 'E', 'Y', ' ') which is a constant value &H2059454D.
2. Use the MCI open command except to add a plus sign (+) at the end of a file name. For instance, open test.MEY+ type waveaudio (or avivideo) alias test. Because there is a "+" character in the file name, mmioOpen will not open any files. Instead, the custom mmio procedure is identified. Subsequently, all the I/O messages are routed to that procedure.
3.Then, we can use usual MCI command. For instance: play test, close test
4. When done with this custom mmio procedure, we should remove it by mmioInstallIOProc(MEY, ByVal 0&, MMIO_REMOVEPROC)
Where MEY=&H2059454D '//Const value of mmioFOURCC('M', 'E', 'Y', ' ')
Step-By-Step Example
- Create a standard exe project - Add one module - Add one command button and one picturebox control on the form1 - Add the following code to form1 Note : Alter resource file path, resource id and resource type name if its different than specified in this demo. I have included a test.exe file which contains AVI resource so you can use it for de Form1.frm |
Click here to copy the following block | Option Explicit Private Sub Command1_Click() Dim hRsrc As Long Dim hGlobal As Long Dim lpString As String Dim strCmd As String, ret As Long Dim nbuf As Long
lpString = "#101"
hInst = LoadLibrary(App.Path & "\test.exe") hRsrc = FindResource(hInst, lpString, "AVI") hGlobal = LoadResource(hInst, hRsrc) lpData = LockResource(hGlobal) fileSize = SizeofResource(hInst, hRsrc)
Call mmioInstallIOProc(MEY, AddressOf IOProc, MMIO_INSTALLPROC + MMIO_GLOBALPROC) nbuf = 256 Call mciSendString("Close all", 0&, 0&, 0&) strCmd = "open test.MEY+ type avivideo alias test parent " & Picture1.hWnd & " Style child" ret = mciSendString(strCmd, 0&, 0&, 0&) If ret > 0 Then ShowMCIError (ret) strCmd = "play test repeat" ret = mciSendString(strCmd, 0&, 0&, 0&) If ret > 0 Then ShowMCIError (ret) Call mmioInstallIOProc(MEY, vbNull, MMIO_REMOVEPROC) FreeLibrary hInst End Sub
Private Sub Form_Load() Command1.Caption = "Play AVI from Memory" End Sub |
- Add the following code to module1
Module1.bas |
Click here to copy the following block | Option Explicit Public lpData As Long Public fileSize As Long Public hInst As Long
Public Const MMIO_INSTALLPROC = &H10000
Public Const MMIO_GLOBALPROC = &H10000000
Public Const MMIO_READ = &H0 Public Const MMIOM_CLOSE = 4 Public Const MMIOM_OPEN = 3 Public Const MMIOM_READ = MMIO_READ Public Const MMIO_REMOVEPROC = &H20000 Public Const MMIOM_SEEK = 2 Public Const SEEK_CUR = 1 Public Const SEEK_END = 2 Public Const SEEK_SET = 0 Public Const MEY = &H2059454D
Public Type MMIOINFO dwFlags As Long fccIOProc As Long pIOProc As Long wErrorRet As Long htask As Long cchBuffer As Long pchBuffer As String pchNext As String pchEndRead As String pchEndWrite As String lBufOffset As Long lDiskOffset As Long adwInfo(4) As Long dwReserved1 As Long dwReserved2 As Long hmmio As Long End Type
Public Declare Function FindResource Lib "kernel32" Alias "FindResourceA" ( _ ByVal hInstance As Long, _ ByVal lpName As String, _ ByVal lpType As String) As Long
Public Declare Function LoadResource Lib "kernel32" ( _ ByVal hInstance As Long, _ ByVal hResInfo As Long) As Long
Public Declare Function LockResource Lib "kernel32" ( _ ByVal hResData As Long) As Long
Public Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" ( _ ByVal lpLibFileName As String) As Long
Public Declare Function FreeLibrary Lib "kernel32" _ (ByVal hLibModule As Long) As Long
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _ hpvDest As Any, _ hpvSource As Any, _ ByVal cbCopy As Long)
Public Declare Function mmioInstallIOProc Lib "winmm" Alias "mmioInstallIOProcA" ( _ ByVal fccIOProc As Long, _ ByVal pIOProc As Long, _ ByVal dwFlags As Long) As Long
Public Declare Function mciSendString Lib "winmm.dll" Alias "mciSendStringA" ( _ ByVal lpstrCommand As String, _ ByVal lpstrReturnString As Long, _ ByVal uReturnLength As Long, _ ByVal hwndCallback As Long) As Long
Public Declare Function mciGetErrorString Lib "winmm.dll" Alias "mciGetErrorStringA" ( _ ByVal ErrorNumber As Long, _ ByVal ReturnBuffer As String, _ ByVal ReturnBufferSize As Long) As Long
Public Declare Function SizeofResource Lib "kernel32" ( _ ByVal hInstance As Long, _ ByVal hResInfo As Long) As Long
Public Function IOProc(ByRef lpMMIOInfo As MMIOINFO, ByVal uMessage As Long, _ ByVal lParam1 As Long, _ ByVal lParam2 As Long) As Long
Static alreadyOpened As Boolean
Select Case uMessage Case MMIOM_OPEN If Not alreadyOpened Then alreadyOpened = True lpMMIOInfo.lDiskOffset = 0 End If IOProc = 0
Case MMIOM_CLOSE IOProc = 0
Case MMIOM_READ: Call CopyMemory(ByVal lParam1, ByVal _ lpData + lpMMIOInfo.lDiskOffset, lParam2) lpMMIOInfo.lDiskOffset = lpMMIOInfo.lDiskOffset + lParam2 IOProc = lParam2
Case MMIOM_SEEK
Select Case lParam2 Case SEEK_SET lpMMIOInfo.lDiskOffset = lParam1
Case SEEK_CUR lpMMIOInfo.lDiskOffset = lpMMIOInfo.lDiskOffset + lParam1 lpMMIOInfo.lDiskOffset = fileSize - 1 - lParam1
Case SEEK_END lpMMIOInfo.lDiskOffset = fileSize - 1 - lParam1 End Select
IOProc = lpMMIOInfo.lDiskOffset
Case Else IOProc = -1 End Select
End Function
Public Function ShowMCIError(Optional ByVal errNum As Long) Dim strMsg As String
errNum = LOWORD(errNum)
strMsg = String(260, Chr(0)) If mciGetErrorString(errNum, strMsg, 260) <> 0 Then MsgBox Left(strMsg, InStr(strMsg, Chr(0)) - 1), vbCritical, "Error: " & errNum Else MsgBox "Unknown Error", vbCritical, "Error: " & errNum End If End Function
Private Function LOWORD(ByVal dwValue As Long) As Integer LOWORD = Val("&H" & Right("0000" & Hex(dwValue), 4)) End Function |
|