public int OnNotify(IntPtr NotifyData)
{
//Since AUDIO_VOLUME_NOTIFICATION_DATA is dynamic in length based on the
//number of audio channels available we cannot just call PtrToStructure
//to get all data, thats why it is split up into two steps, first the static
//data is marshalled into the data structure, then with some IntPtr math the
//remaining floats are read from memory.
//
AUDIO_VOLUME_NOTIFICATION_DATA data = (AUDIO_VOLUME_NOTIFICATION_DATA)Marshal.PtrToStructure(NotifyData, typeof(AUDIO_VOLUME_NOTIFICATION_DATA));
//Determine offset in structure of the first float
IntPtr Offset = Marshal.OffsetOf(typeof(AUDIO_VOLUME_NOTIFICATION_DATA), "ChannelVolume");
//Determine offset in memory of the first float
IntPtr FirstFloatPtr = (IntPtr)((long)NotifyData + (long)Offset);
float[] voldata = new float[data.nChannels];
//Read all floats from memory.
for (int i = 0; i < data.nChannels; i++)
{
voldata[i] = (float)Marshal.PtrToStructure(FirstFloatPtr, typeof(float));
}
//Create combined structure and Fire Event in parent class.
AudioVolumeNotificationData NotificationData = new AudioVolumeNotificationData(data.guidEventContext, data.bMuted, data.fMasterVolume, voldata);
_Parent.FireNotification(NotificationData);
return 0; //S_OK
}