// ----------------------------------------- // SoundScribe (TM) and related software. // // Copyright (C) 2007-2011 Vannatech // http://www.vannatech.com // All rights reserved. // // This source code is subject to the MIT License. // http://www.opensource.org/licenses/mit-license.php // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // ----------------------------------------- using System; using System.Runtime.InteropServices; using CoreAudioTests.Common; using Microsoft.VisualStudio.TestTools.UnitTesting; using Vannatech.CoreAudio.Constants; using Vannatech.CoreAudio.Enumerations; using Vannatech.CoreAudio.Externals; using Vannatech.CoreAudio.Interfaces; namespace CoreAudioTests.MMDeviceApi { /// /// Tests all methods of the IMMDevice interface. /// [TestClass] public class IMMDeviceTest { /// /// This test ensures that each device can use any valid COM interface returned from the Activate method. /// It checks to make sure each received interface is not null and an HRESULT of S_OK is returned. /// [TestMethod] public void IMMDevice_Activate() { var devices = TestUtilities.CreateIMMDeviceCollection(EDataFlow.eAll, DEVICE_STATE_XXX.DEVICE_STATE_ACTIVE); foreach (var d in devices) { var iid = Guid.Empty; var result = -1; object objInterface = null; // Check IAudioClient iid = new Guid(ComIIDs.IAudioClientIID); result = d.Activate(iid, (uint)CLSCTX.CLSCTX_INPROC_SERVER, IntPtr.Zero, out objInterface); AssertCoreAudio.IsHResultOk(result); Assert.IsNotNull(objInterface as IAudioClient); // Check IAudioEndpointVolume iid = new Guid(ComIIDs.IAudioEndpointVolumeIID); result = d.Activate(iid, (uint)CLSCTX.CLSCTX_INPROC_SERVER, IntPtr.Zero, out objInterface); AssertCoreAudio.IsHResultOk(result); Assert.IsNotNull(objInterface as IAudioEndpointVolume); // Check IAudioMeterInformation iid = new Guid(ComIIDs.IAudioMeterInformationIID); result = d.Activate(iid, (uint)CLSCTX.CLSCTX_INPROC_SERVER, IntPtr.Zero, out objInterface); AssertCoreAudio.IsHResultOk(result); Assert.IsNotNull(objInterface as IAudioMeterInformation); // Check IAudioSessionManager iid = new Guid(ComIIDs.IAudioSessionManagerIID); result = d.Activate(iid, (uint)CLSCTX.CLSCTX_INPROC_SERVER, IntPtr.Zero, out objInterface); AssertCoreAudio.IsHResultOk(result); Assert.IsNotNull(objInterface as IAudioSessionManager); // Check IAudioSessionManager2 iid = new Guid(ComIIDs.IAudioSessionManager2IID); result = d.Activate(iid, (uint)CLSCTX.CLSCTX_INPROC_SERVER, IntPtr.Zero, out objInterface); AssertCoreAudio.IsHResultOk(result); Assert.IsNotNull(objInterface as IAudioSessionManager2); // Check IDeviceTopology iid = new Guid(ComIIDs.IDeviceTopologyIID); result = d.Activate(iid, (uint)CLSCTX.CLSCTX_INPROC_SERVER, IntPtr.Zero, out objInterface); AssertCoreAudio.IsHResultOk(result); Assert.IsNotNull(objInterface as IDeviceTopology); } } /// /// This test ensures that each device can get its ID. It also checks that the received ID is not null. /// [TestMethod] public void IMMDevice_GetId() { var devices = TestUtilities.CreateIMMDeviceCollection(); foreach (var d in devices) { string strId; var result = d.GetId(out strId); AssertCoreAudio.IsHResultOk(result); Assert.IsNotNull(strId); } } /// /// This test ensures that each device can get its state. It also checks that the received state is a valid device state constant. /// [TestMethod] public void IMMDevice_GetState() { var devices = TestUtilities.CreateIMMDeviceCollection(); foreach (var d in devices) { UInt32 deviceState; var result = d.GetState(out deviceState); AssertCoreAudio.IsHResultOk(result); AssertCoreAudio.IsDeviceStateValid(deviceState); } } /// /// This test ensures that each device can open a property store in READWRITE mode and that the received property store is non-null. /// It also checks that the property store object works correctly by making a call to get the property count. /// [TestMethod] public void IMMDevice_OpenPropertyStore() { var tested = false; var devices = TestUtilities.CreateIMMDeviceCollection(); foreach (var d in devices) { // Open the property store IPropertyStore propertyStore; var result = d.OpenPropertyStore(STGM.STGM_READ, out propertyStore); AssertCoreAudio.IsHResultOk(result); // Verify the count can be received. var propertyCount = UInt32.MaxValue; result = propertyStore.GetCount(out propertyCount); AssertCoreAudio.IsHResultOk(result); Assert.AreNotEqual(UInt32.MaxValue, propertyCount, "The property count was not received."); // Get each property key, then get value. for (uint i = 0; i < propertyCount; i++) { PROPERTYKEY propertyKey; result = propertyStore.GetAt(i, out propertyKey); AssertCoreAudio.IsHResultOk(result); var value = GetPropertyValue(propertyStore, propertyKey); if (value != null) tested = true; } } if (!tested) Assert.Inconclusive("No property values returned valid, non-null values."); } private object GetPropertyValue(IPropertyStore propertyStore, PROPERTYKEY propertyKey) { object returnObj = null; PROPVARIANT propVariant; var result = propertyStore.GetValue(ref propertyKey, out propVariant); AssertCoreAudio.IsHResultOk(result); var vType = (VarEnum)propVariant.vt; if (vType == VarEnum.VT_EMPTY) return null; switch (vType) { case VarEnum.VT_BOOL: returnObj = propVariant.Data.AsBoolean; break; case VarEnum.VT_UI4: returnObj = propVariant.Data.AsUInt32; break; case VarEnum.VT_LPWSTR: case VarEnum.VT_CLSID: returnObj = Marshal.PtrToStringUni(propVariant.Data.AsStringPtr); break; case VarEnum.VT_BLOB: returnObj = propVariant.Data.AsFormatPtr; break; } if (propertyKey.fmtid == PropertyKeys.PKEY_AudioEngine_DeviceFormat || propertyKey.fmtid == PropertyKeys.PKEY_AudioEngine_OEMFormat) { Assert.AreEqual(VarEnum.VT_BLOB, vType, "The device format property was not of varient type VT_BLOB."); var format = (WAVEFORMATEX)Marshal.PtrToStructure((IntPtr)returnObj, typeof(WAVEFORMATEX)); if (format.nChannels != 0 && format.nSamplesPerSec != 0 && format.wBitsPerSample != 0) Assert.AreEqual(format.nChannels * format.nSamplesPerSec * format.wBitsPerSample, format.nAvgBytesPerSec * 8, "The wave format was not valid."); } return returnObj; } } }