aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Speech/ISpeechProvider.cs
blob: eb31bdc39e7b7fd0236e69e509874ead8e3ffc85 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Tango.MachineStudio.Common.Speech
{
    /// <summary>
    /// Represents a text to speech engine.
    /// </summary>
    public interface ISpeechProvider
    {
        /// <summary>
        /// Gets or sets a value indicating whether this <see cref="ISpeechProvider"/> is mute.
        /// </summary>
        bool Mute { get; set; }

        /// <summary>
        /// Speaks the specified text associated with an information sound.
        /// </summary>
        /// <param name="text">The text.</param>
        void SpeakInfo(String text);

        /// <summary>
        /// Speaks the specified text associated with an error sound.
        /// </summary>
        /// <param name="text">The text.</param>
        void SpeakError(String text);
    }
}
adding-left: 5px; padding-right: 5px; } span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } .highlight .hll { background-color: #ffffcc } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
using DirectShowLib;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Security.Permissions;
using System.Text;
using System.Threading.Tasks;

namespace Tango.Video.DirectShow
{
    internal class DSUtils
    {
        public static void SetSampleGrabber(IBaseFilter filter, SampleGrabberImpl sampleGrabberImpl)
        {
            var pVideoSampleGrabber = (ISampleGrabber)filter;
            var mtVideo = new AMMediaType { majorType = MediaType.Video, subType = MediaSubType.RGB24 };
            pVideoSampleGrabber.SetMediaType(mtVideo);
            pVideoSampleGrabber.SetBufferSamples(false);
            pVideoSampleGrabber.SetOneShot(false);
            pVideoSampleGrabber.SetCallback(sampleGrabberImpl, 1);
            DirectShowLib.DsUtils.FreeAMMediaType(mtVideo);
        }

        public static void SetSampleGrabber2(IBaseFilter filter, SampleGrabberImpl sampleGrabberImpl)
        {
            var pVideoSampleGrabber = (ISampleGrabber)filter;
            var mtVideo = new AMMediaType { majorType = MediaType.Video, subType = MediaSubType.RGB24 };
            pVideoSampleGrabber.SetMediaType(mtVideo);
            pVideoSampleGrabber.SetBufferSamples(false);
            pVideoSampleGrabber.SetOneShot(false);
            pVideoSampleGrabber.SetCallback(sampleGrabberImpl, 0);
            DirectShowLib.DsUtils.FreeAMMediaType(mtVideo);
        }

        public static IBaseFilter GetVideoInputDeviceFilter(Device device)
        {
            return GetFilterByNameAndCat(device);
        }
        /// <summary>
        /// Create IBaseFilter from the specified category by the specified name.
        /// </summary>
        /// <param name="category"></param>
        /// <param name="filterName"></param>
        /// <returns></returns>
        public static IBaseFilter GetFilterByNameAndCat(Device device)
        {
            object source = null;
            var iid = (typeof(IBaseFilter)).GUID;
            var devices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice);

            foreach (DsDevice d in devices)
            {
                if (d.DevicePath == device.DevicePath)
                {
                    d.Mon.BindToObject(null, null, ref iid, out source);
                    break;
                }
            }

            return (IBaseFilter)source;
        }

        public static List<Device> GetVideoInputDevices()
        {
            var devices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice);
            return devices.Select(device => new Device() { DevicePath = device.DevicePath, Name = device.Name }).ToList();
        }

        /// <summary>
        /// Connect 2 filters. This is a special implementation of connect filters. It will loop through
        /// all of the unconnected output pins of the source filter and all of the unconnected input pins of the destination filter
        /// and it will try any connection, between any of the 2 pairs of pins. On the first succesfull connection
        /// it will return.
        /// </summary>
        /// <param name="graph">IGraphBuilder where source and destination filter are added.</param>
        /// <param name="pSrc">Source filter.</param>
        /// <param name="pDst">Destination filter.</param>
        /// <returns>true if the connection is succesfull, otherwise false.</returns>
        [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
        public static bool ConnectFiltersTryAllPins(IGraphBuilder graph, IBaseFilter pSrc, IBaseFilter pDst)
        {
            int srcPins = CountPins(pSrc, PinDirection.Output);
            int dstPins = CountPins(pDst, PinDirection.Input);
            bool connection = false;
            for (int i = 0; i < srcPins; i++)
            {
                IPin pSrcPin = GetPinAtIndex(pSrc, PinDirection.Output, i, false);
                if (pSrcPin == null) continue;

                for (int j = 0; j < dstPins; j++)
                {
                    IPin pDstPin = GetPinAtIndex(pDst, PinDirection.Input, j, false);
                    if (pDstPin == null) continue;

                    int hr = graph.Connect(pSrcPin, pDstPin);

                    connection = (hr == 0) || (hr == 262722); // S_OK or VFW_S_PARTIAL_RENDER= 0x00040242 (262722)

                    Marshal.ReleaseComObject(pDstPin);
                    if (connection) break;
                }

                Marshal.ReleaseComObject(pSrcPin);
                if (connection) break;
            }
            return connection;
        }

        /// <summary>
        /// Count all of the pins on a filter with a specified direction.
        /// </summary>
        /// <param name="pFilter">Filter to count pins for.</param>
        /// <param name="pinDir">Pin direction required to count pins for.</param>
        /// <returns></returns>
        [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
        public static int CountPins(IBaseFilter pFilter, PinDirection pinDir)
        {
            IEnumPins enumPins;
            var pins = new IPin[1];

            int hr = pFilter.EnumPins(out enumPins);
            if (hr != 0) return 0;

            var nrPins = 0;
            try
            {
                while (enumPins.Next(pins.Length, pins, IntPtr.Zero) == 0)
                {
                    try
                    {
                        PinInfo pinInfo;
                        hr = pins[0].QueryPinInfo(out pinInfo);
                        if (pinInfo.dir == pinDir)
                        {
                            nrPins++;
                        }

                        if (pinInfo.filter != null)
                            Marshal.ReleaseComObject(pinInfo.filter);
                    }
                    finally
                    {
                        Marshal.ReleaseComObject(pins[0]);
                    }
                }
            }
            finally
            {
                if (enumPins != null)
                    Marshal.ReleaseComObject(enumPins);
            }

            return nrPins;
        }
        
        /// <summary>
        /// Get pin at a specified index on a filter.
        /// </summary>
        /// <param name="pFilter">IBaseFilter to find pin on.</param>
        /// <param name="pinDir">Pin direction.</param>
        /// <param name="index">Zero based index of the pin. Indexes are counted depending on the pin direction.</param>
        /// <param name="connected">Should the pin be connected or not.</param>
        /// <returns></returns>
        [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
        public static IPin GetPinAtIndex(IBaseFilter pFilter, PinDirection pinDir, int index, bool connected)
        {
            IEnumPins enumPins;
            var pins = new IPin[1];

            int hr = pFilter.EnumPins(out enumPins);
            if (hr != 0) return null;

            var nrPins = -1;
            bool found = false;
            try
            {
                while (enumPins.Next(pins.Length, pins, IntPtr.Zero) == 0)
                {
                    try
                    {
                        PinInfo pinInfo;
                        hr = pins[0].QueryPinInfo(out pinInfo);
                        if (pinInfo.dir == pinDir)
                        {
                            nrPins++;
                        }

                        if (pinInfo.filter != null)
                            Marshal.ReleaseComObject(pinInfo.filter);

                        // Check if a pin is connected
                        IPin pConPin = null;
                        pins[0].ConnectedTo(out pConPin);
                        if (pConPin != null && !connected)
                        {
                            Marshal.ReleaseComObject(pConPin);
                            continue;
                        }
                        else if (pConPin == null && connected) continue;

                        if (nrPins == index)
                        {
                            found = true;
                            break;
                        }
                    }
                    finally
                    {
                        if (!found)
                            Marshal.ReleaseComObject(pins[0]);
                    }
                }
            }
            finally
            {
                if (enumPins != null)
                    Marshal.ReleaseComObject(enumPins);
            }

            return pins[0];
        }

        /// <summary>
        /// Searches for the next connected filter. If the start filter is connected to some downstream
        /// filter it will return that filter, otherwise, null.
        /// </summary>
        /// <param name="pGraph"></param>
        /// <param name="pStartFilter"></param>
        /// <returns></returns>
        [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
        public static IBaseFilter GetNextConnectedFilter(IGraphBuilder pGraph, IBaseFilter pStartFilter)
        {
            int pinCount = CountPins(pStartFilter, PinDirection.Output);
            IBaseFilter pReturnFilter = null;
            for (int i = 0; i < pinCount; i++)
            {
                IPin pOutPin = GetPinAtIndex(pStartFilter, PinDirection.Output, i, true);
                if (pOutPin != null)
                {
                    IPin pConnectedToPin = null;
                    pOutPin.ConnectedTo(out pConnectedToPin);
                    if (pConnectedToPin != null)
                    {
                        PinInfo pinInfo;
                        pConnectedToPin.QueryPinInfo(out pinInfo);
                        pReturnFilter = pinInfo.filter;
                        Marshal.ReleaseComObject(pConnectedToPin);
                    }

                    Marshal.ReleaseComObject(pOutPin);
                }

                if (pReturnFilter != null) break;
            }
            return pReturnFilter;
        }

        /// <summary>
        /// Save a DirectShow Graph to a GRF file
        /// </summary>
        /// <param name="graphBuilder">the IGraphBuilder interface of the graph</param>
        /// <param name="fileName">the file to be saved</param>
        /// <exception cref="System.ArgumentNullException">Thrown if graphBuilder is null</exception>
        /// <exception cref="System.Runtime.InteropServices.COMException">Thrown if errors occur during the file creation</exception>
        /// <seealso cref="LoadGraphFile"/>
        /// <remarks>This method overwrites any existing file</remarks>
        [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
        public static void SaveGraphFile(IGraphBuilder graphBuilder, string fileName)
        {
            int hr = 0;
            IStorage storage = null;
#if USING_NET11
            UCOMIStream stream = null;
#else
            IStream stream = null;
#endif

            if (graphBuilder == null)
                throw new ArgumentNullException("graphBuilder");

            try
            {
                hr = NativeMethods.StgCreateDocfile(
                    fileName,
                    STGM.Create | STGM.Transacted | STGM.ReadWrite | STGM.ShareExclusive,
                    0,
                    out storage
                    );

                Marshal.ThrowExceptionForHR(hr);

                hr = storage.CreateStream(
                    @"ActiveMovieGraph",
                    STGM.Write | STGM.Create | STGM.ShareExclusive,
                    0,
                    0,
                    out stream
                    );

                Marshal.ThrowExceptionForHR(hr);

                hr = (graphBuilder as IPersistStream).Save(stream, true);
                Marshal.ThrowExceptionForHR(hr);

                hr = storage.Commit(STGC.Default);
                Marshal.ThrowExceptionForHR(hr);
            }
            finally
            {
                if (stream != null)
                    Marshal.ReleaseComObject(stream);
                if (storage != null)
                    Marshal.ReleaseComObject(storage);
            }
        }
    }
}