Results 1 to 1 of 1

Thread: [VB6, Vista+] Core Audio - Monitor for disabled/active, default, and property changes

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    7,654

    [VB6, Vista+] Core Audio - Monitor for disabled/active, default, and property changes


    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
    Then the notification class, cMMNotify, is set up just to assign the data and fire off a window message:
    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
    OnPropertyChanged, which uses a PROPERTYKEY, is even weirder. See the class module comments for more details.

    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)
    As the code suggests, this project also shows how to convert a device ID to the friendly name.

    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)





    twinBASIC 64bit-compatible version can be found at: https://github.com/fafalone/CoreAudioDemos
    Attached Files Attached Files
    Last edited by fafalone; May 28th, 2026 at 12:43 AM.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width