aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/Utilities/Tango.BugReporter/Tango.BugReporter.csproj
blob: e0450c4bfe6e30531c9cf13ddc41eb4ccf03a7db (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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProjectGuid>{C8F14D59-B18D-469C-8B1B-2D23072ED16A}</ProjectGuid>
    <OutputType>Exe</OutputType>
    <RootNamespace>Tango.BugReporter</RootNamespace>
    <AssemblyName>Tango.BugReporter</AssemblyName>
    <TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <PlatformTarget>AnyCPU</PlatformTarget>
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <PlatformTarget>AnyCPU</PlatformTarget>
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="MigraDoc.DocumentObjectModel, Version=1.32.4334.0, Culture=neutral, PublicKeyToken=f94615aa0424f9eb, processorArchitecture=MSIL">
      <HintPath>..\..\packages\PDFsharp-MigraDoc-GDI.1.32.4334.0\lib\net20\MigraDoc.DocumentObjectModel.dll</HintPath>
    </Reference>
    <Reference Include="MigraDoc.Rendering, Version=1.32.4334.0, Culture=neutral, PublicKeyToken=f94615aa0424f9eb, processorArchitecture=MSIL">
      <HintPath>..\..\packages\PDFsharp-MigraDoc-GDI.1.32.4334.0\lib\net20\MigraDoc.Rendering.dll</HintPath>
    </Reference>
    <Reference Include="MigraDoc.RtfRendering, Version=1.32.4334.0, Culture=neutral, PublicKeyToken=f94615aa0424f9eb, processorArchitecture=MSIL">
      <HintPath>..\..\packages\PDFsharp-MigraDoc-GDI.1.32.4334.0\lib\net20\MigraDoc.RtfRendering.dll</HintPath>
    </Reference>
    <Reference Include="PdfSharp, Version=1.32.3057.0, Culture=neutral, PublicKeyToken=f94615aa0424f9eb, processorArchitecture=MSIL">
      <HintPath>..\..\packages\PDFsharp-MigraDoc-GDI.1.32.4334.0\lib\net20\PdfSharp.dll</HintPath>
    </Reference>
    <Reference Include="PdfSharp.Charting, Version=1.32.3057.0, Culture=neutral, PublicKeyToken=f94615aa0424f9eb, processorArchitecture=MSIL">
      <HintPath>..\..\packages\PDFsharp-MigraDoc-GDI.1.32.4334.0\lib\net20\PdfSharp.Charting.dll</HintPath>
    </Reference>
    <Reference Include="System" />
    <Reference Include="System.Core" />
    <Reference Include="System.Drawing" />
    <Reference Include="System.Xml.Linq" />
    <Reference Include="System.Data.DataSetExtensions" />
    <Reference Include="Microsoft.CSharp" />
    <Reference Include="System.Data" />
    <Reference Include="System.Net.Http" />
    <Reference Include="System.Xml" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Program.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
  </ItemGroup>
  <ItemGroup>
    <None Include="App.config" />
    <None Include="packages.config" />
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="..\..\Tango.Core\Tango.Core.csproj">
      <Project>{a34ee0f0-649d-41c8-8489-b6f1cc6924ee}</Project>
      <Name>Tango.Core</Name>
    </ProjectReference>
    <ProjectReference Include="..\..\Tango.TFS\Tango.TFS.csproj">
      <Project>{998f8471-dc1b-41b6-9d96-354e1b4e7a32}</Project>
      <Name>Tango.TFS</Name>
    </ProjectReference>
  </ItemGroup>
  <ItemGroup>
    <Content Include="bug.png">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
    <Content Include="task.png">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
    <Content Include="twine-logo.jpg">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Tango.Video.DirectShow;
using Tango.Video.DirectShow.EventArguments;
using Tango.Video.DirectShow.Delegates;


namespace Tango.Video.DirectCapture
{
    /// <summary>
    /// Represents a capture device object. This is a dependency object.
    /// </summary>
    public class CaptureDevice : DependencyObject, INotifyPropertyChanged, IDisposable
    {
        private DirectShowCapture captureDevice;
        private WriteableBitmap blackSource;
        private int updateSourceCounter;

        #region Events

        /// <summary>
        /// Raises then a new frame has been received from the capture device.
        /// </summary>
        /// <example><code>
        ///void capture_FrameReceived(object sender, DirectShow.EventArguments.FrameReceivedEventArgs args)
        ///{
        ///    //Use this event to draw on, or manipulate the frames.
        ///    //This will be triggered only if RaiseFrameReceivedEvent is set to true.
        ///    //To show the manipulated image, unbind the img args from the VideoSource property in the xaml file.
        ///
        ///    args.BitmapSource.Lock();
        ///
        ///    System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(args.BitmapSource.PixelWidth, args.BitmapSource.PixelHeight, args.BitmapSource.BackBufferStride, System.Drawing.Imaging.PixelFormat.Format24bppRgb, args.BitmapSource.BackBuffer);
        ///    System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bmp);
        ///
        ///    //Draw on the frame using good old GDI+
        ///    g.FillEllipse(System.Drawing.Brushes.Red, new System.Drawing.Rectangle(20, 20, 100, 100));
        ///    g.DrawString("Process The Frames ;)", new System.Drawing.Font("Arial", 24), System.Drawing.Brushes.White, new System.Drawing.RectangleF(140, 50, 400, 50));
        ///
        ///    g.Dispose();
        ///    bmp.Dispose();
        ///
        ///    args.BitmapSource.AddDirtyRect(new Int32Rect(0, 0, args.BitmapSource.PixelWidth, args.BitmapSource.PixelHeight));
        ///    args.BitmapSource.Unlock();
        ///    args.BitmapSource.Freeze();
        ///
        ///    this.Dispatcher.BeginInvoke(new Action(() =>
        ///    {
        ///        postImage.Source = args.BitmapSource; //This event is raising from a seperate thread so we need to invoke the UI dispatcher.
        ///    }));
        ///}
        /// </code></example>
        public event FrameReceivedEventDelegate FrameReceived;

        /// <summary>
        /// Occurs when a video capture has started.
        /// </summary>
        public event Action CaptureStarted;

        /// <summary>
        /// Occurs when a video capture has stoped.
        /// </summary>
        public event Action CaptureStoped;

        #endregion

        #region Constructors

        public CaptureDevice()
        {
            captureDevice = new DirectShowCapture();
            captureDevice.FrameReceived += captureDevice_FrameReceived;
            captureDevice.UseFrameRate = false;
            captureDevice.UseFrameSize = false;
            captureDevice.UseQueue = false;

            updateSourceCounter = 0;
            UpdateSourceRatio = 1;

            //Initialize Black Source
            blackSource = new WriteableBitmap(Tango.Video.DirectShow.BitmapHelper.CreateEmptySource(new Size(1920, 1080), Colors.Transparent));
            blackSource.Freeze();


            //Initialize Available Sources.
            List<Device> list = Tango.Video.DirectShow.DirectShowCapture.GetAvailableDevices();
            AvailableCaptureDevices = new ObservableCollection<Device>(list);


            //Initialize Standard Resolutions.
            List<Resolution> res = new List<Resolution>();
            res.Add(new Resolution(320, 240));
            res.Add(new Resolution(640, 480));
            res.Add(new Resolution(720, 576));
            res.Add(new Resolution(800, 600));
            res.Add(new Resolution(1024, 768));
            res.Add(new Resolution(1280, 720));
            res.Add(new Resolution(1280, 1024));
            res.Add(new Resolution(1440, 900));
            res.Add(new Resolution(1366, 768));
            res.Add(new Resolution(1600, 900));
            res.Add(new Resolution(1680, 1050));
            res.Add(new Resolution(1600, 1200));
            res.Add(new Resolution(1920, 1080));
            res.Add(new Resolution(1920, 1200));
            StandardResolutions = new ObservableCollection<Resolution>(res);


            //Initialize Standard Frame Rates.
            List<FrameRate> rates = new List<FrameRate>();
            rates.Add(new FrameRate(5));
            rates.Add(new FrameRate(10));
            rates.Add(new FrameRate(15));
            rates.Add(new FrameRate(20));
            rates.Add(new FrameRate(23.98));
            rates.Add(new FrameRate(29.97));
            rates.Add(new FrameRate(50));
            rates.Add(new FrameRate(60));
            StandardFrameRates = new ObservableCollection<FrameRate>(rates);
        }

        #endregion

        #region Event Handlers

        private void captureDevice_FrameReceived(object sender, FrameReceivedEventArgs args)
        {
            this.Dispatcher.BeginInvoke(new Action(() =>
            {
                updateSourceCounter++;

                if (updateSourceCounter >= UpdateSourceRatio)
                {
                    VideoSource = args.BitmapSource;
                    updateSourceCounter = 0;
                }

                if (!_isStarted && ClearSourceOnStop)
                {
                    BindSourceToBlackSource();
                }

            }), System.Windows.Threading.DispatcherPriority.Send);

            if (_raiseFrameReceivedEvent)
            {
                OnFrameReceived(this, new FrameReceivedEventArgs(BitmapHelper.BitmapSourceToWriteableBitmap(args.BitmapSource)));
            }
        }

        #endregion

        #region Properties

        private bool _emulatedMode;
        /// <summary>
        /// Gets or sets a value indicating whether [video available].
        /// </summary>
        public bool EmulatedMode
        {
            get { return _emulatedMode; }
            set { _emulatedMode = value; RaisePropertyChanged(nameof(EmulatedMode)); }
        }


        /// <summary>
        /// The name of the device to capture.
        /// </summary>
        public Device Device
        {
            get { return (Device)GetValue(DeviceProperty); }
            set { SetValue(DeviceProperty, value); }
        }
        public static readonly DependencyProperty DeviceProperty =
            DependencyProperty.Register("Device", typeof(Device), typeof(CaptureDevice), new PropertyMetadata(null, new PropertyChangedCallback(DeviceNameChanged)));
        private static void DeviceNameChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            CaptureDevice instance = GetInstance(d);
            instance.captureDevice.VideoDevice = instance.Device;

            if (instance.IsStarted && instance.InvalidateSourceOnPropertiesChange)
            {
                instance.InvalidateDevice();
            }
        }


        /// <summary>
        /// Sets the frame rate of the capture device.
        /// </summary>
        public FrameRate FrameRate
        {
            get { return (FrameRate)GetValue(FrameRateProperty); }
            set { SetValue(FrameRateProperty, value); }
        }
        public static readonly DependencyProperty FrameRateProperty =
            DependencyProperty.Register("FrameRate", typeof(FrameRate), typeof(CaptureDevice), new PropertyMetadata(new FrameRate(15), new PropertyChangedCallback(FrameRateChanged)));
        private static void FrameRateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var instance = GetInstance(d);

            if (instance.FrameRate != null)
            {
                instance.captureDevice.FrameRate = instance.FrameRate.Rate;

                if (instance.IsStarted && instance.InvalidateSourceOnPropertiesChange)
                {
                    instance.InvalidateDevice();
                }
            }
        }


        /// <summary>
        /// When set to true, the capture device will use the default frame rate.
        /// </summary>
        public bool AutoFrameRate
        {
            get { return (bool)GetValue(AutoFrameRateProperty); }
            set 
            {
                SetValue(AutoFrameRateProperty, value);
                captureDevice.UseFrameRate = !AutoFrameRate;
            }
        }
        public static readonly DependencyProperty AutoFrameRateProperty =
            DependencyProperty.Register("AutoFrameRate", typeof(bool), typeof(CaptureDevice), new PropertyMetadata(true, new PropertyChangedCallback(AutoFrameRateChanged)));
        private static void AutoFrameRateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var instance = GetInstance(d);
            instance.captureDevice.UseFrameRate = !instance.AutoFrameRate;
        }


        /// <summary>
        /// Sets the capture device frame width.
        /// </summary>
        public int FrameWidth
        {
            get { return (int)GetValue(FrameWidthProperty); }
            set 
            {
                SetValue(FrameWidthProperty, value);
                captureDevice.FrameSize = new FrameSize(FrameWidth, FrameHeight);
            }
        }
        public static readonly DependencyProperty FrameWidthProperty =
            DependencyProperty.Register("FrameWidth", typeof(int), typeof(CaptureDevice), new PropertyMetadata(1280, new PropertyChangedCallback(FrameWidthChanged)));
        private static void FrameWidthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var instance = GetInstance(d);
            instance.captureDevice.FrameSize = new FrameSize(instance.FrameWidth, instance.FrameHeight);
        }


        /// <summary>
        /// Sets the capture device frame height.
        /// </summary>
        public int FrameHeight
        {
            get { return (int)GetValue(FrameHeightProperty); }
            set 
            {
                SetValue(FrameHeightProperty, value);
                captureDevice.FrameSize = new FrameSize(FrameWidth, FrameHeight);
            }
        }
        public static readonly DependencyProperty FrameHeightProperty =
            DependencyProperty.Register("FrameHeight", typeof(int), typeof(CaptureDevice), new PropertyMetadata(720, new PropertyChangedCallback(FrameHeightChanged)));
        private static void FrameHeightChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var instance = GetInstance(d);
            instance.captureDevice.FrameSize = new FrameSize(instance.FrameWidth, instance.FrameHeight);
        }


        /// <summary>
        /// Then set to true, the capture device will use the default frame size.
        /// </summary>
        public bool AutoFrameSize
        {
            get { return (bool)GetValue(AutoFrameSizeProperty); }
            set { SetValue(AutoFrameSizeProperty, value); }
        }
        public static readonly DependencyProperty AutoFrameSizeProperty =
            DependencyProperty.Register("AutoFrameSize", typeof(bool), typeof(CaptureDevice), new PropertyMetadata(true, new PropertyChangedCallback(AutoFrameSizeChanged)));
        private static void AutoFrameSizeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var instance = GetInstance(d);
            instance.captureDevice.UseFrameSize = !instance.AutoFrameSize;
        }


        /// <summary>
        /// Use this property to bind your image args to.
        /// </summary>
        public BitmapSource VideoSource
        {
            get { return (BitmapSource)GetValue(VideoSourceProperty); }
            set { SetValue(VideoSourceProperty, value); }
        }
        public static readonly DependencyProperty VideoSourceProperty =
            DependencyProperty.Register("VideoSource", typeof(BitmapSource), typeof(CaptureDevice), new PropertyMetadata(null));


        /// <summary>
        /// Contains a list of available capture device names.
        /// </summary>
        public ObservableCollection<Device> AvailableCaptureDevices
        {
            get { return (ObservableCollection<Device>)GetValue(AvailableCaptureDevicesProperty); }
            set { SetValue(AvailableCaptureDevicesProperty, value); }
        }
        public static readonly DependencyProperty AvailableCaptureDevicesProperty =
            DependencyProperty.Register("AvailableCaptureDevices", typeof(ObservableCollection<Device>), typeof(CaptureDevice), new PropertyMetadata(null));


        /// <summary>
        /// Use this property as an alternative to set the capture device frame width and height.
        /// </summary>
        public Resolution Resolution
        {
            get { return (Resolution)GetValue(ResolutionProperty); }
            set { SetValue(ResolutionProperty, value); }
        }
        public static readonly DependencyProperty ResolutionProperty =
            DependencyProperty.Register("Resolution", typeof(Resolution), typeof(CaptureDevice), new PropertyMetadata(null, new PropertyChangedCallback(ResolutionChanged)));
        private static void ResolutionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var instance = GetInstance(d);

            if (instance.Resolution != null)
            {
                instance.captureDevice.FrameSize = new FrameSize(instance.Resolution.Width, instance.Resolution.Height);

                if (instance.IsStarted && instance.InvalidateSourceOnPropertiesChange)
                {
                    instance.InvalidateDevice();
                }
            }
        }


        /// <summary>
        /// Contains a list of standard resolutions for any capture device.
        /// </summary>
        public ObservableCollection<Resolution> StandardResolutions
        {
            get { return (ObservableCollection<Resolution>)GetValue(StandardResolutionsProperty); }
            set { SetValue(StandardResolutionsProperty, value); }
        }
        public static readonly DependencyProperty StandardResolutionsProperty =
            DependencyProperty.Register("StandardResolutions", typeof(ObservableCollection<Resolution>), typeof(CaptureDevice), new PropertyMetadata(null));


        /// <summary>
        /// Contains a list of standard frame rates for any capture device.
        /// </summary>
        public ObservableCollection<FrameRate> StandardFrameRates
        {
            get { return (ObservableCollection<FrameRate>)GetValue(StandardFrameRatesProperty); }
            set { SetValue(StandardFrameRatesProperty, value); }
        }
        public static readonly DependencyProperty StandardFrameRatesProperty =
            DependencyProperty.Register("StandardFrameRates", typeof(ObservableCollection<FrameRate>), typeof(CaptureDevice), new PropertyMetadata(null));


        /// <summary>
        /// Gets or sets whether to reconnect the capture device if resolution, frame rate or device name were changed.
        /// </summary>
        public bool InvalidateSourceOnPropertiesChange
        {
            get { return (bool)GetValue(InvalidateSourceOnPropertiesChangeProperty); }
            set { SetValue(InvalidateSourceOnPropertiesChangeProperty, value); }
        }
        public static readonly DependencyProperty InvalidateSourceOnPropertiesChangeProperty =
            DependencyProperty.Register("InvalidateSourceOnPropertiesChange", typeof(bool), typeof(CaptureDevice), new PropertyMetadata(false));


        /// <summary>
        /// Gets or sets whether to clear the image args when the capture device stops.
        /// </summary>
        public bool ClearSourceOnStop
        {
            get { return (bool)GetValue(ClearSourceOnStopProperty); }
            set { SetValue(ClearSourceOnStopProperty, value); }
        }
        public static readonly DependencyProperty ClearSourceOnStopProperty =
            DependencyProperty.Register("ClearSourceOnStop", typeof(bool), typeof(CaptureDevice), new PropertyMetadata(false));


        private bool _raiseFrameReceivedEvent;
        /// <summary>
        /// Gets or sets whether to raise the FrameReceived event. (Set to true if you want to manipulate the args).
        /// </summary>
        public bool RaiseFrameReceivedEvent
        {
            get { return _raiseFrameReceivedEvent; }
            set
            {
                if (_raiseFrameReceivedEvent && !value && _isStarted)
                {
                    BindSourceToDirectShow();
                }

                _raiseFrameReceivedEvent = value;

                RaisePropertyChanged("RaiseFrameReceivedEvent");

                captureDevice.UseQueue = value;
            }
        }


        private bool _isStarted;
        /// <summary>
        /// Gets or sets whether the capture device is capturing.
        /// </summary>
        public bool IsStarted
        {
            get { return _isStarted; }
            set
            {
                _isStarted = value;
                RaisePropertyChanged("IsStarted");

                if (value)
                {
                    Start();
                }
                else
                {
                    Stop();
                }
            }
        }


        private int updateSourceRatio;
        /// <summary>
        /// Gets or sets the dependepncy property video source update frequency.
        /// </summary>
        public int UpdateSourceRatio
        {   
            get { return updateSourceRatio; }
            set { updateSourceRatio = value; RaisePropertyChanged("UpdateSourceRatio"); }
        }
        

        #endregion

        #region Public Methods

        /// <summary>
        /// Starts the capture device.
        /// </summary>
        public void Start()
        {
            BindSourceToDirectShow();

            _isStarted = true;
            RaisePropertyChanged("IsStarted");

            if (!IsInDesignMode())
            {
                captureDevice.Start();
            }

            if (CaptureStarted != null) CaptureStarted();
        }


        /// <summary>
        /// Stops the capture device.
        /// </summary>
        public void Stop()
        {
            _isStarted = false;
            RaisePropertyChanged("IsStarted");

            if (!IsInDesignMode())
            {
                captureDevice.Stop();
            }

            if (ClearSourceOnStop)
            {
                BindSourceToBlackSource();

                if (_raiseFrameReceivedEvent)
                {
                    OnFrameReceived(this, new FrameReceivedEventArgs(new WriteableBitmap(BitmapHelper.CreateEmptySource(new Size(1920, 1080), Colors.Transparent))));
                }
            }

            if (CaptureStoped != null) CaptureStoped();
        }


        /// <summary>
        /// Use this method to bind an image control to the video args property.
        /// </summary>
        /// <param name="image">The image control</param>
        /// <returns>The binding instance that was used to create the binding.</returns>
        public Binding BindImageSourceToVideoSource(Image image)
        {
            Binding b = new Binding();
            b.Source = this;
            b.Path = new PropertyPath(CaptureDevice.VideoSourceProperty);
            b.Mode = BindingMode.OneWay;
            b.IsAsync = true;
            b.BindsDirectlyToSource = true;
            image.SetBinding(Image.SourceProperty, b);

            return b;
        }


        /// <summary>
        /// Use this method to bind any control background to the video args property.
        /// </summary>
        /// <param name="control">Any type that is a control or inharits from control.</param>
        /// <returns>The binding instance that was used to create the binding.</returns>
        public Binding BindControlBackgroundToVideoSource(Control control)
        {
            Binding b = new Binding();
            b.Source = this;
            b.Path = new PropertyPath(CaptureDevice.VideoSourceProperty);
            b.Mode = BindingMode.OneWay;
            b.IsAsync = true;
            b.BindsDirectlyToSource = true;
            control.SetBinding(Control.BackgroundProperty, b);

            return b;
        }

        public void DisableSourceUpdate()
        {
            EmulatedMode = true;
            this.Unbind(CaptureDevice.VideoSourceProperty);
        }

        public void EnableSourceUpdate()
        {
            EmulatedMode = false;
            BindSourceToDirectShow();
        }

        #endregion

        #region Private Methods
        private void BindSourceToDirectShow()
        {
            this.BindAsync(CaptureDevice.VideoSourceProperty, captureDevice, DirectShowCapture.SourceProperty, BindingMode.OneWay);
        }

        private void BindSourceToBlackSource()
        {
            VideoSource = blackSource;
        }

        private bool IsInDesignMode()
        {
            return (DesignerProperties.GetIsInDesignMode(this));
        }

        private void InvalidateDevice()
        {
            try
            {
                captureDevice.Stop();
                captureDevice.Start();
            }
            catch { }
        }
        #endregion

        #region Static Methods

        private static CaptureDevice GetInstance(DependencyObject d)
        {
            return d as CaptureDevice;
        }

        /// <summary>
        /// Retrieves all the available capture devices supporting direct show.
        /// </summary>
        /// <returns>Device names.</returns>
        public static List<Device> GetAvailableCaptureDevices()
        {
            return DirectShowCapture.GetAvailableDevices();
        }

        #endregion

        #region Virtuals

        protected virtual void OnFrameReceived(object sender, FrameReceivedEventArgs args)
        {
            if (FrameReceived != null) FrameReceived(sender, args);
        }

        #endregion

        #region IDisposable Members

        /// <summary>
        /// Stops and disposes the current instance.
        /// </summary>
        public void Dispose()
        {
            _isStarted = false;
            captureDevice.Stop();
        }

        #endregion

        #region Notify Property Changed Members
        public event PropertyChangedEventHandler PropertyChanged;

        private void RaisePropertyChanged(String propName)
        {
            if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }
        #endregion
    }
}