
Monitoring audio hardware for changes
At first glance, the IMMNotificationClient interface looks like it's simple and straightforward. And in the IDE it is, but it turns out when compiled all normal ways of accessing the passed values results in a crash. Getting around this involves putting the variables into a public structure that can only be accessed and processed by subclassing the main form and using PostMessage to send the message to process things.
Setting up the notifications is easy enough:
Code:
Private Sub Command1_Click()
Command1.Enabled = False
hFrm = Me.hwnd
Subclass2 Me.hwnd, AddressOf F1WndProc, Me.hwnd
SetNotify
End Sub
Private Sub SetNotify()
Dim hr As Long
If (mDeviceEnum Is Nothing) Then
Set mDeviceEnum = New MMDeviceEnumerator
End If
If (cMMNotify Is Nothing) Then
Set cMMNotify = New cMMNotificationClient
hr = mDeviceEnum.RegisterEndpointNotificationCallback(cMMNotify)
AddMsg "Registered cMMNotify, hr=" & Hex$(hr)
End If
End Sub
Code:
Private Sub IMMNotificationClient_OnDeviceStateChanged(ByVal pwstrDeviceId As Long, ByVal dwNewState As DEVICE_STATE)
tPVC.lpszID = pwstrDeviceId
tPVC.pid = dwNewState
PostMessage hFrm, WM_MMONDEVICESTATECHANGE, 0&, ByVal 0&
End Sub
Our custom WM_MMx messages then get handled in a normal subclassing WndProc:
Code:
Select Case uMsg
Case WM_MMONDEVICESTATECHANGE
sPtr = LPWSTRtoStr(tPVC.lpszID, False)
Form1.AddMsg "StateChange: DeviceID: " & sPtr
Form1.AddMsg "Name=" & Form1.GetDeviceName(sPtr)
Form1.AddMsg "New status=" & GetStatusStr(tPVC.pid)
Since all messages are handled with API posting, the project should be free of instabilities that cause a crash. I haven't had crashes in testing both for the IDE and once compiled. Always unregister the notification callback before unloading the form containing an instance of the class, or the app crashes on exit (the demo project handles this automatically in Form_Unload)
Requirements
-Windows Vista or newer
-oleexp.tlb v4.0 or higher (only needed for the IDE)
-mPKEY.bas (included in oleexp download)