예제 #1
0
파일: AudioWMA.cs 프로젝트: zxc120/GARbro
        private static long GetDuration(IMFSourceReader reader)
        {
            var variantPtr = Marshal.AllocHGlobal(MarshalHelpers.SizeOf <PropVariant>());

            try
            {
                int hResult = reader.GetPresentationAttribute(MediaFoundationInterop.MF_SOURCE_READER_MEDIASOURCE,
                                                              MediaFoundationAttributes.MF_PD_DURATION, variantPtr);
                if (hResult == MediaFoundationErrors.MF_E_ATTRIBUTENOTFOUND)
                {
                    return(0);
                }
                if (hResult != 0)
                {
                    Marshal.ThrowExceptionForHR(hResult);
                }

                var variant = MarshalHelpers.PtrToStructure <PropVariant> (variantPtr);
                return((long)variant.Value);
            }
            finally
            {
                PropVariant.Clear(variantPtr);
                Marshal.FreeHGlobal(variantPtr);
            }
        }
예제 #2
0
        private long GetLength(IMFSourceReader reader)
        {
            var variantPtr = Marshal.AllocHGlobal(MarshalHelpers.SizeOf <PropVariant>());

            try
            {
                // http://msdn.microsoft.com/en-gb/library/windows/desktop/dd389281%28v=vs.85%29.aspx#getting_file_duration
                int hResult = reader.GetPresentationAttribute(MediaFoundationInterop.MF_SOURCE_READER_MEDIASOURCE,
                                                              MediaFoundationAttributes.MF_PD_DURATION, variantPtr);
                if (hResult == MediaFoundationErrors.MF_E_ATTRIBUTENOTFOUND)
                {
                    // this doesn't support telling us its duration (might be streaming)
                    return(0);
                }
                if (hResult != 0)
                {
                    Marshal.ThrowExceptionForHR(hResult);
                }
                var variant = MarshalHelpers.PtrToStructure <PropVariant>(variantPtr);

                var lengthInBytes = (((long)variant.Value) * waveFormat.AverageBytesPerSecond) / 10000000L;
                return(lengthInBytes);
            }
            finally
            {
                PropVariant.Clear(variantPtr);
                Marshal.FreeHGlobal(variantPtr);
            }
        }
예제 #3
0
        public void 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.
            //
            var data = MarshalHelpers.PtrToStructure <AudioVolumeNotificationDataStruct>(notifyData);

            //Determine offset in structure of the first float
            var offset = MarshalHelpers.OffsetOf <AudioVolumeNotificationDataStruct>("ChannelVolume");
            //Determine offset in memory of the first float
            var firstFloatPtr = (IntPtr)((long)notifyData + (long)offset);

            var voldata = new float[data.nChannels];

            //Read all floats from memory.
            for (int i = 0; i < data.nChannels; i++)
            {
                voldata[i] = MarshalHelpers.PtrToStructure <float>(firstFloatPtr);
            }

            //Create combined structure and Fire Event in parent class.
            var notificationData = new AudioVolumeNotificationData(data.guidEventContext, data.bMuted, data.fMasterVolume, voldata, data.guidEventContext);

            parent.FireNotification(notificationData);
        }
예제 #4
0
파일: AudioClient.cs 프로젝트: jnm2/NAudio
        /// <summary>
        /// Determines if the specified output format is supported in shared mode
        /// </summary>
        /// <param name="shareMode">Share Mode</param>
        /// <param name="desiredFormat">Desired Format</param>
        /// <param name="closestMatchFormat">Output The closest match format.</param>
        /// <returns>True if the format is supported</returns>
        public bool IsFormatSupported(AudioClientShareMode shareMode, WaveFormat desiredFormat, out WaveFormatExtensible closestMatchFormat)
        {
            IntPtr pointerToPtr = GetPointerToPointer(); // IntPtr.Zero; // Marshal.AllocHGlobal(Marshal.SizeOf<WaveFormatExtensible>());

            closestMatchFormat = null;
            int hresult = audioClientInterface.IsFormatSupported(shareMode, desiredFormat, pointerToPtr);

            var closestMatchPtr = MarshalHelpers.PtrToStructure <IntPtr>(pointerToPtr);

            if (closestMatchPtr != IntPtr.Zero)
            {
                closestMatchFormat = MarshalHelpers.PtrToStructure <WaveFormatExtensible>(closestMatchPtr);
                Marshal.FreeCoTaskMem(closestMatchPtr);
            }
            Marshal.FreeHGlobal(pointerToPtr);
            // S_OK is 0, S_FALSE = 1
            if (hresult == 0)
            {
                // directly supported
                return(true);
            }
            if (hresult == 1)
            {
                return(false);
            }
            if (hresult == (int)AudioClientErrors.UnsupportedFormat)
            {
                // Succeeded but the specified format is not supported in exclusive mode.
                return(shareMode != AudioClientShareMode.Exclusive);
            }
            Marshal.ThrowExceptionForHR(hresult);
            // shouldn't get here
            throw new NotSupportedException("Unknown hresult " + hresult);
        }
예제 #5
0
        /// <summary>
        /// Helper function to retrieve a WaveFormat structure from a pointer
        /// </summary>
        /// <param name="pointer">WaveFormat structure</param>
        /// <returns></returns>
        public static WaveFormat MarshalFromPtr(IntPtr pointer)
        {
            var waveFormat = MarshalHelpers.PtrToStructure <WaveFormat>(pointer);

            switch (waveFormat.Encoding)
            {
            case WaveFormatEncoding.Pcm:
                // can't rely on extra size even being there for PCM so blank it to avoid reading
                // corrupt data
                waveFormat.extraSize = 0;
                break;

            case WaveFormatEncoding.Extensible:
                waveFormat = MarshalHelpers.PtrToStructure <WaveFormatExtensible>(pointer);
                break;

            case WaveFormatEncoding.Adpcm:
                //  waveFormat = MarshalHelpers.PtrToStructure<AdpcmWaveFormat>(pointer);
                break;

            case WaveFormatEncoding.Gsm610:
                // waveFormat = MarshalHelpers.PtrToStructure<Gsm610WaveFormat>(pointer);
                break;

            default:
                if (waveFormat.ExtraSize > 0)
                {
                    waveFormat = MarshalHelpers.PtrToStructure <WaveFormatExtraData>(pointer);
                }
                break;
            }
            return(waveFormat);
        }
예제 #6
0
        public bool IsFormatSupported(AudioClientShareMode shareMode, WaveFormat desiredFormat, out WaveFormatExtensible closestMatchFormat)
        {
            IntPtr pointerToPointer = this.GetPointerToPointer();

            closestMatchFormat = null;
            int    num    = this.audioClientInterface.IsFormatSupported(shareMode, desiredFormat, pointerToPointer);
            IntPtr intPtr = MarshalHelpers.PtrToStructure <IntPtr>(pointerToPointer);

            if (intPtr != IntPtr.Zero)
            {
                closestMatchFormat = MarshalHelpers.PtrToStructure <WaveFormatExtensible>(intPtr);
                Marshal.FreeCoTaskMem(intPtr);
            }
            Marshal.FreeHGlobal(pointerToPointer);
            if (num == 0)
            {
                return(true);
            }
            if (num == 1)
            {
                return(false);
            }
            if (num == -2004287480)
            {
                return(shareMode != AudioClientShareMode.Exclusive);
            }
            Marshal.ThrowExceptionForHR(num);
            throw new NotSupportedException("Unknown hresult " + num);
        }
예제 #7
0
        private long GetLength(IMFSourceReader reader)
        {
            IntPtr intPtr = Marshal.AllocHGlobal(MarshalHelpers.SizeOf <PropVariant>());
            long   result;

            try
            {
                int presentationAttribute = reader.GetPresentationAttribute(-1, MediaFoundationAttributes.MF_PD_DURATION, intPtr);
                if (presentationAttribute == -1072875802)
                {
                    result = 0L;
                }
                else
                {
                    if (presentationAttribute != 0)
                    {
                        Marshal.ThrowExceptionForHR(presentationAttribute);
                    }
                    result = (long)MarshalHelpers.PtrToStructure <PropVariant>(intPtr).Value *(long)this.waveFormat.AverageBytesPerSecond / 10000000L;
                }
            }
            finally
            {
                PropVariant.Clear(intPtr);
                Marshal.FreeHGlobal(intPtr);
            }
            return(result);
        }
예제 #8
0
 /// <summary>
 /// Gets the details for this control
 /// </summary>
 protected override void GetDetails(IntPtr pDetails)
 {
     unsignedDetails = new MixerInterop.MIXERCONTROLDETAILS_UNSIGNED[nChannels];
     for (int channel = 0; channel < nChannels; channel++)
     {
         unsignedDetails[channel] = MarshalHelpers.PtrToStructure <MixerInterop.MIXERCONTROLDETAILS_UNSIGNED>(mixerControlDetails.paDetails);
     }
 }
예제 #9
0
        /// <summary>
        /// Gets a specified Mixer Control
        /// </summary>
        /// <param name="mixerHandle">Mixer Handle</param>
        /// <param name="nLineId">Line ID</param>
        /// <param name="controlId">Control ID</param>
        /// <param name="nChannels">Number of Channels</param>
        /// <param name="mixerFlags">Flags to use (indicates the meaning of mixerHandle)</param>
        /// <returns></returns>
        public static MixerControl GetMixerControl(IntPtr mixerHandle, int nLineId, int controlId, int nChannels,
                                                   MixerFlags mixerFlags)
        {
            var mlc = new MixerInterop.MIXERLINECONTROLS();
            var mc  = new MixerInterop.MIXERCONTROL();

            // set up the pointer to a structure
            IntPtr pMixerControl = Marshal.AllocCoTaskMem(Marshal.SizeOf(mc));

            //Marshal.StructureToPtr(mc, pMixerControl, false);

            mlc.cbStruct    = Marshal.SizeOf(mlc);
            mlc.cControls   = 1;
            mlc.dwControlID = controlId;
            mlc.cbmxctrl    = Marshal.SizeOf(mc);
            mlc.pamxctrl    = pMixerControl;
            mlc.dwLineID    = nLineId;
            MmResult err = MixerInterop.mixerGetLineControls(mixerHandle, ref mlc, MixerFlags.OneById | mixerFlags);

            if (err != MmResult.NoError)
            {
                Marshal.FreeCoTaskMem(pMixerControl);
                throw new MmException(err, "mixerGetLineControls");
            }

            // retrieve the structure from the pointer
            mc = MarshalHelpers.PtrToStructure <MixerInterop.MIXERCONTROL>(mlc.pamxctrl);
            Marshal.FreeCoTaskMem(pMixerControl);

            if (IsControlBoolean(mc.dwControlType))
            {
                return(new BooleanMixerControl(mc, mixerHandle, mixerFlags, nChannels));
            }

            if (IsControlSigned(mc.dwControlType))
            {
                return(new SignedMixerControl(mc, mixerHandle, mixerFlags, nChannels));
            }

            if (IsControlUnsigned(mc.dwControlType))
            {
                return(new UnsignedMixerControl(mc, mixerHandle, mixerFlags, nChannels));
            }

            if (IsControlListText(mc.dwControlType))
            {
                return(new ListTextMixerControl(mc, mixerHandle, mixerFlags, nChannels));
            }

            if (IsControlCustom(mc.dwControlType))
            {
                return(new CustomMixerControl(mc, mixerHandle, mixerFlags, nChannels));
            }

            throw new InvalidOperationException($"Unknown mixer control type {mc.dwControlType}");
        }
예제 #10
0
        private static void AddAttribute(IMFActivate mft, int index, StringBuilder sb)
        {
            var variantPtr = Marshal.AllocHGlobal(MarshalHelpers.SizeOf <PropVariant>());

            try
            {
                Guid key;
                mft.GetItemByIndex(index, out key, variantPtr);
                var    value        = MarshalHelpers.PtrToStructure <PropVariant>(variantPtr);
                string propertyName = FieldDescriptionHelper.Describe(typeof(MediaFoundationAttributes), key);
                if (key == MediaFoundationAttributes.MFT_INPUT_TYPES_Attributes ||
                    key == MediaFoundationAttributes.MFT_OUTPUT_TYPES_Attributes)
                {
                    var types = value.GetBlobAsArrayOf <MFT_REGISTER_TYPE_INFO>();
                    sb.AppendFormat("{0}: {1} items:", propertyName, types.Length);
                    sb.AppendLine();
                    foreach (var t in types)
                    {
                        sb.AppendFormat("    {0}-{1}",
                                        FieldDescriptionHelper.Describe(typeof(MediaTypes), t.guidMajorType),
                                        FieldDescriptionHelper.Describe(typeof(AudioSubtypes), t.guidSubtype));
                        sb.AppendLine();
                    }
                }
                else if (key == MediaFoundationAttributes.MF_TRANSFORM_CATEGORY_Attribute)
                {
                    sb.AppendFormat("{0}: {1}", propertyName,
                                    FieldDescriptionHelper.Describe(typeof(MediaFoundationTransformCategories), (Guid)value.Value));
                    sb.AppendLine();
                }
                else if (value.DataType == (VarEnum.VT_VECTOR | VarEnum.VT_UI1))
                {
                    var b = (byte[])value.Value;
                    sb.AppendFormat("{0}: Blob of {1} bytes", propertyName, b.Length);
                    sb.AppendLine();
                }
                else
                {
                    sb.AppendFormat("{0}: {1}", propertyName, value.Value);
                    sb.AppendLine();
                }
            }
            finally
            {
                PropVariant.Clear(variantPtr);
                Marshal.FreeHGlobal(variantPtr);
            }
        }
예제 #11
0
        private static void DescribeAttribute(IMFMediaType mediaType, int n, StringBuilder sb)
        {
            var variantPtr = Marshal.AllocHGlobal(MarshalHelpers.SizeOf <PropVariant>());

            try
            {
                Guid key;
                mediaType.GetItemByIndex(n, out key, variantPtr);
                var    val          = MarshalHelpers.PtrToStructure <PropVariant>(variantPtr);
                string propertyName = FieldDescriptionHelper.Describe(typeof(MediaFoundationAttributes), key);
                sb.AppendFormat("{0}={1}\r\n", propertyName, val.Value);
            }
            finally
            {
                PropVariant.Clear(variantPtr);
                Marshal.FreeHGlobal(variantPtr);
            }
        }
예제 #12
0
        public void OnNotify(IntPtr notifyData)
        {
            AudioVolumeNotificationDataStruct audioVolumeNotificationDataStruct = MarshalHelpers.PtrToStructure <AudioVolumeNotificationDataStruct>(notifyData);
            IntPtr value   = MarshalHelpers.OffsetOf <AudioVolumeNotificationDataStruct>("ChannelVolume");
            IntPtr pointer = (IntPtr)((long)notifyData + (long)value);

            float[] array = new float[audioVolumeNotificationDataStruct.nChannels];
            int     num   = 0;

            while ((long)num < (long)((ulong)audioVolumeNotificationDataStruct.nChannels))
            {
                array[num] = MarshalHelpers.PtrToStructure <float>(pointer);
                num++;
            }
            AudioVolumeNotificationData notificationData = new AudioVolumeNotificationData(audioVolumeNotificationDataStruct.guidEventContext, audioVolumeNotificationDataStruct.bMuted, audioVolumeNotificationDataStruct.fMasterVolume, array, audioVolumeNotificationDataStruct.guidEventContext);

            this.parent.FireNotification(notificationData);
        }
예제 #13
0
        /// <summary>
        /// Gets all the mixer controls
        /// </summary>
        /// <param name="mixerHandle">Mixer Handle</param>
        /// <param name="mixerLine">Mixer Line</param>
        /// <param name="mixerHandleType">Mixer Handle Type</param>
        /// <returns></returns>
        public static IList <MixerControl> GetMixerControls(IntPtr mixerHandle, MixerLine mixerLine,
                                                            MixerFlags mixerHandleType)
        {
            var controls = new List <MixerControl>();

            if (mixerLine.ControlsCount > 0)
            {
                int    mixerControlSize = MarshalHelpers.SizeOf <MixerInterop.MIXERCONTROL>();
                var    mlc = new MixerInterop.MIXERLINECONTROLS();
                IntPtr pmc = Marshal.AllocHGlobal(mixerControlSize * mixerLine.ControlsCount);
                mlc.cbStruct  = Marshal.SizeOf(mlc);
                mlc.dwLineID  = mixerLine.LineId;
                mlc.cControls = mixerLine.ControlsCount;
                mlc.pamxctrl  = pmc;
                mlc.cbmxctrl  = MarshalHelpers.SizeOf <MixerInterop.MIXERCONTROL>();
                try
                {
                    MmResult err = MixerInterop.mixerGetLineControls(mixerHandle, ref mlc, MixerFlags.All | mixerHandleType);
                    if (err != MmResult.NoError)
                    {
                        throw new MmException(err, "mixerGetLineControls");
                    }
                    for (int i = 0; i < mlc.cControls; i++)
                    {
                        Int64 address = pmc.ToInt64() + mixerControlSize * i;

                        var mc =
                            MarshalHelpers.PtrToStructure <MixerInterop.MIXERCONTROL>((IntPtr)address);
                        var mixerControl = GetMixerControl(mixerHandle, mixerLine.LineId, mc.dwControlID, mixerLine.Channels,
                                                           mixerHandleType);

                        controls.Add(mixerControl);
                    }
                }
                finally
                {
                    Marshal.FreeHGlobal(pmc);
                }
            }
            return(controls);
        }
예제 #14
0
        public static WaveFormat MarshalFromPtr(IntPtr pointer)
        {
            WaveFormat         waveFormat = MarshalHelpers.PtrToStructure <WaveFormat>(pointer);
            WaveFormatEncoding encoding   = waveFormat.Encoding;

            if (encoding <= WaveFormatEncoding.Adpcm)
            {
                if (encoding == WaveFormatEncoding.Pcm)
                {
                    waveFormat.extraSize = 0;
                    return(waveFormat);
                }
                if (encoding == WaveFormatEncoding.Adpcm)
                {
                    waveFormat = MarshalHelpers.PtrToStructure <AdpcmWaveFormat>(pointer);
                    return(waveFormat);
                }
            }
            else
            {
                if (encoding == WaveFormatEncoding.Gsm610)
                {
                    waveFormat = MarshalHelpers.PtrToStructure <Gsm610WaveFormat>(pointer);
                    return(waveFormat);
                }
                if (encoding == WaveFormatEncoding.Extensible)
                {
                    waveFormat = MarshalHelpers.PtrToStructure <WaveFormatExtensible>(pointer);
                    return(waveFormat);
                }
            }
            if (waveFormat.ExtraSize > 0)
            {
                waveFormat = MarshalHelpers.PtrToStructure <WaveFormatExtraData>(pointer);
            }
            return(waveFormat);
        }
예제 #15
0
        /// <summary>
        /// Determines if the specified output format is supported in shared mode
        /// </summary>
        /// <param name="shareMode">Share Mode</param>
        /// <param name="desiredFormat">Desired Format</param>
        /// <param name="closestMatchFormat">Output The closest match format.</param>
        /// <returns>True if the format is supported</returns>
        public bool IsFormatSupported(AudioClientShareMode shareMode, WaveFormat desiredFormat, out WaveFormatExtensible closestMatchFormat)
        {
            IntPtr pointerToPtr = GetPointerToPointer(); // IntPtr.Zero; // Marshal.AllocHGlobal(Marshal.SizeOf<WaveFormatExtensible>());

            closestMatchFormat = null;
            int hresult = audioClientInterface.IsFormatSupported(shareMode, desiredFormat, pointerToPtr);

            var closestMatchPtr = MarshalHelpers.PtrToStructure <IntPtr>(pointerToPtr);

            if (closestMatchPtr != IntPtr.Zero)
            {
                closestMatchFormat = MarshalHelpers.PtrToStructure <WaveFormatExtensible>(closestMatchPtr);
                Marshal.FreeCoTaskMem(closestMatchPtr);
            }
            Marshal.FreeHGlobal(pointerToPtr);
            // S_OK is 0, S_FALSE = 1
            if (hresult == 0)
            {
                // directly supported
                return(true);
            }
            if (hresult == 1)
            {
                return(false);
            }
            if (hresult == (int)AudioClientErrors.UnsupportedFormat)
            {
                // documentation is confusing as to what this flag means
                // https://docs.microsoft.com/en-us/windows/desktop/api/audioclient/nf-audioclient-iaudioclient-isformatsupported
                // "Succeeded but the specified format is not supported in exclusive mode."
                return(false); // shareMode != AudioClientShareMode.Exclusive;
            }
            Marshal.ThrowExceptionForHR(hresult);
            // shouldn't get here
            throw new NotSupportedException("Unknown hresult " + hresult);
        }
 /// <summary>
 /// Gets details for this contrl
 /// </summary>
 protected override void GetDetails(IntPtr pDetails)
 {
     signedDetails = MarshalHelpers.PtrToStructure <MixerInterop.MIXERCONTROLDETAILS_SIGNED>(mixerControlDetails.paDetails);
 }
예제 #17
0
 /// <summary>
 /// Gets the details for this control
 /// </summary>
 /// <param name="pDetails">memory pointer</param>
 protected override void GetDetails(IntPtr pDetails)
 {
     boolDetails = MarshalHelpers.PtrToStructure <MixerInterop.MIXERCONTROLDETAILS_BOOLEAN>(pDetails);
 }