martedì 11 giugno 2013

E poi venne DYNAMIC

Lo so lo so sono un pazzo furioso, ammetto tutte le mie colpe ma credo davvero che mi sia spalancata la porta del sapere.
Questa mattina mi stavo arrovellando il cervello su come gestire una connettività fra classi in modo che si attivino come un Cromatoforo di un polpo.
Per chi non conoscesse l'argomento il cromatoforo, è un cellula della pelle di un polpo o di una seppia, che consente se stimolata di modificare il suo stato. La "vera fissa" di questa entità e che lavora in gruppo.
Di contro se questo fosse ralizzabile in ambito "software" sarebbe davvero qualcosa di unico.. immaginate classi di calcolo che lavorano all'unisono solo se sono sollecitate o classi di calcolo che sanno che sollecitare per lavorare... Mi vengono in mente mille soluzioni, e mille ipotesi. Ma per il momento mi godo questo momento e non penso ad altro.
(non è vero sto renderizzando ... )

Dynamic è qualcosa di "astratto" ma concreto non saprei dare una definizione, non è generic, benchè sia generico ha il vantaggio di non dover ( farti ) implementare invocatori di metodi con reflection.

Ma non attendo altro .. questo è il mio esempio.. VS2010 framework 4

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Dynamic
{
    class Program
    {
        static void Main(string[] args)
        {

            DynamicDataProvider d0 = new DynamicDataProvider(0);
            entities et0 = d0.GetEntities();

            Console.WriteLine("Real Data provider");
            for (int i = 0; i < et0.Count(); i++)
            {
                Console.WriteLine(et0[i].id + "\t" + et0[i].name);
            }

            DynamicDataProvider d1 = new DynamicDataProvider(1);
            entities et1 = d1.GetEntities();

            Console.WriteLine("Mock Data provider");
            for (int i = 0; i < et1.Count(); i++)
            {
                Console.WriteLine(et1[i].id + "\t" + et1[i].name);
            }


            Console.WriteLine("Dynamc Real Data provider");
            dynamic dd = new DynamicDataProvider(0);
            var etn = dd.GetEntities();
            
            foreach (dynamic e in etn)
            {
                Console.WriteLine(e.id + "\t" + e.name);
            }


            Console.WriteLine("Dynamc fake Data provider");
            dynamic dd1 = new DynamicDataProvider(3);
            var etn1 = dd1.GetEntities();

            foreach (dynamic e in etn1)
            {
                Console.WriteLine(e.id + "\t" + e.name);
            }


            Console.ReadLine();

        }
    }

    public class entity
    {
        public int id { get; set; }
        public string name { get; set; }
        public string description { get; set; }
    }


    public class entityBis
    {
        public int id { get; set; }
        public string name { get; set; }
        public string value { get; set; }
    }

    public class entities : List<entity>
    {     
    }


    public class entitiesBis : List<entityBis>
    {
    }


    public class DynamicDataProvider
    {
        int retType = 0;

        public DynamicDataProvider(int cType)
        {
            retType = cType;
        }

        public dynamic GetEntities()
        {
            if (retType == 0)
            {
                return new realDataProvider().fillEntites();
            }
            if ( retType == 1)
            {
                return new mockDataProvider().fillEntites();
            }

            return new fakeDataProvider().fillEntites();
        }

    }

    public class realDataProvider
    {
        public entities fillEntites()
        {
            entities entx = new entities();
            entx.Add(new entity() { id = 1, 
                                    name = "default", 
                                    description = "" });
            entx.Add(new entity() { id = 2, 
                                    name = "one", 
                                    description = "" });
            entx.Add(new entity() { id = 3, 
                                    name = "many", 
                                    description = "" });
            entx.Add(new entity() { id = 4, 
                                    name = "nome", 
                                    description = "" });


            return entx;
        }
    }

    public class fakeDataProvider
    {
        public entitiesBis fillEntites()
        {
            entitiesBis entx = new entitiesBis();
            entx.Add(new entityBis() { id = 1, 
                                       name = "default Bis", 
                                       value = "1" });
            entx.Add(new entityBis() { id = 2, 
                                       name = "one Bis", 
                                       value = "2" });
            entx.Add(new entityBis() { id = 3, 
                                       name = "many Bis", 
                                       value = "3" });
            entx.Add(new entityBis() { id = 4, 
                                       name = "nome Bis", 
                                       value = "4" });


            return entx;
        }
    }


    public class mockDataProvider
    {
        public entities fillEntites()
        {
            entities entx = new entities();
            entx.Add(new entity() { id = 1, 
                                    name = "mock", 
                                    description = "" });

            return entx;
        }
    }
}


L'unica è prendere questo codice e provarlo in una console application.. realDataProvider e fakeDataProvider propongono lo stesso metodo ma non lo stesso tipo e questo mi gasa particolarmente.
Non basta... le ultime due porzioni di codice del Main sono davvero "potentissime" stesso codice differente risultato su due tipi diversi.
Riesco a immaginare librerie che caricano dinamicamente i plugin certo bisogna stare attenti a come si scrive il codice ma le potenzialità sono davvero tante.

lunedì 10 giugno 2013

How To: Linq Sort / OrderBy

Facendo qualche esperimento mi sono reso conto che l'order by di Linq è meno scomodo di quanto si possa pensare.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestSort
{
    class Program
    {
        static void Main(string[] args)
        {
            entities es = new entities();
            es.Add(new entity() { id = 1, 
                                    name = "fabio", 
                                    description = "nice" });

            es.Add(new entity() { id = 2, 
                                    name = "lorenzo", 
                                    description = "very nice" });

            es.Add(new entity() { id = 2, 
                                    name = "federico", 
                                    description = "it will be" });


            var esx = es.OrderBy(c=> c.name);
            
        }
    }


    public class entity
    {
        public int id { get; set; }
        public string name { get; set; }
        public string description { get; set; }
    }

    public class entities : List<entity>
    { 
    
    }
}

Facile.. no ?

venerdì 31 maggio 2013

How to: C# Lazy ( Side effect )

Recentemente mi sono confrontato con un cordiale discorso di performance.

La maggior parte delle nostre applicazione vive l'ansia di dover caricare dei dati, e a dispetto delle mille possibilità  (leggasi "entity framework" ) non sempre possiamo rivolgerci ad estrattori specifici, o di contro questi sono rappresentati da elementi che wrappano i vare ef.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LazyTester
{
    public class entity
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public string Surname { get; set; }    
    }

    public class entites : List<entity>
    {
        public entites()
        {
            this.Add( new entity(){
                    ID=1,
                    Name = "Fabio",
                    Surname ="Arosio"});

            this.Add( new entity(){
                    ID=2,
                    Name = "Claudio",
                    Surname ="Arosio"});
            
            this.Add( new entity(){
                    ID=3,
                    Name = "Lorenzo",
                    Surname ="Arosio"});
            
            this.Add( new entity(){
                    ID=4,
                    Name = "Federico",
                    Surname ="Arosio"});
            
            Console.WriteLine("done");
        }    
    }

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Lazy...");
            Lazy<entites> ldsE = new Lazy<entites>();
                       

            Console.WriteLine("Normal...");
            entites dsE = new entites();
          
            Console.WriteLine("Normal:"+ dsE.Count.ToString());

            Console.WriteLine("Lazy:" + ldsE.Value.Count.ToString());

            Console.ReadLine();
        }
    }
}


Questo esempietto anche se molto molto scarno presenta il vantaggio di un costruttore Lazy.

già nel nome ben si comprende che cosa farà ma in breve possiamo ipotizzare che quanto costruito come lazy non sarà disponibile fin da subito.
Tanto che la "done" sulla console appare appena prima di della WriteLine Lazy.

Supponiamo giusto per dare visibiltà della situazione che il caricamento differito dei dati avrà luogo solo quando questi saranno necessari e di contro questo "sposta il tempo d'accesso" solo e soltanto a quando questi servono davvero.


var ldsEE = new Lazy<entites>().Value.Where (c=> c.Name.StartsWith("F"));


Ci è lecito pensare e implementare anche in questo modo .. ma perdendone qualche beneficio..

Sicuramente credo che sia sempre cosa buona e giusta sperimentare. !

giovedì 30 maggio 2013

How TO: C# internal WEB CAM r2

La prima versione mi è piaciuta ma onestamente non mi ha soddisfatto, perchè il sorgente era strettamente legato al form, oggi con un filo di calma in più ( giocandomi la pausa ) sono riuscito a migliorare il tutto e il gioco sta nel come gestire le cose.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace CameraCapture.Objects
{
    public class HandledObject
    {
        public int width;
        public int height;
        public Size clientSize;
        public IntPtr handle; 
    }
}


Questo primo oggetto mi serve come tramite per la gestiione dell'Handle... quasi mi sembra di tornare ai fasti delle API a 32bit.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CameraCapture.Objects
{
    public enum PlayState
    {
        Stopped,
        Paused,
        Running,
        Init
    }
}


Questo è rimasto invariato.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DirectShowLib;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;

namespace CameraCapture.Objects
{
    public class DirectShowWrapper
    {

        public int D = Convert.ToInt32("0X8000", 16);

        public int WM_GRAPHNOTIFY = 0;

        public IVideoWindow VideoWindow = null;
        public IMediaControl MediaControl = null;
        public IMediaEventEx MediaEventEx = null;
        public IGraphBuilder GraphBuilder = null;
        public ICaptureGraphBuilder2 CaptureGraphBuilder = null;

        public DsROTEntry rot = null;
        private PlayState CurrentState = PlayState.Stopped;

        public DirectShowWrapper()
        {
            WM_GRAPHNOTIFY = D + 1;
        }

        public void GetInterfaces(HandledObject f)
        {
            int hr = 0;
            this.GraphBuilder = (IGraphBuilder)(new FilterGraph());
            this.CaptureGraphBuilder = (ICaptureGraphBuilder2)(new CaptureGraphBuilder2());
            this.MediaControl = (IMediaControl)(this.GraphBuilder);
            this.VideoWindow = (IVideoWindow)(this.GraphBuilder);
            this.MediaEventEx = (IMediaEventEx)(this.GraphBuilder);
            hr = this.MediaEventEx.SetNotifyWindow(f.handle, 
                                    WM_GRAPHNOTIFY, 
                                    IntPtr.Zero);
        }

        public void CaptureVideo(HandledObject f)
        {
            int hr = 0;
            IBaseFilter sourceFilter = null;
            try
            {
                GetInterfaces(f);

                hr = this.CaptureGraphBuilder.SetFiltergraph(this.GraphBuilder);


                sourceFilter = FindCaptureDevice();

                hr = this.GraphBuilder.AddFilter(sourceFilter, "Video Capture");


                hr = this.CaptureGraphBuilder.RenderStream(PinCategory.Preview,
                        MediaType.Video,
                        sourceFilter,
                        null, null);

                Marshal.ReleaseComObject(sourceFilter);

                SetupVideoWindow(f);

                rot = new DsROTEntry(this.GraphBuilder);

                hr = this.MediaControl.Run();

                this.CurrentState = PlayState.Running;

            }
            catch (Exception ex)
            {

            }
        }

        public void SetupVideoWindow(HandledObject f)
        {
            int hr = 0;

            hr = VideoWindow.put_Owner(f.handle);


            hr = VideoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipChildren);

            ResizeVideoWindow(f);

            hr = VideoWindow.put_Visible(OABool.True);
        }

        public void closeinterfaces()
        {

            if (this.MediaControl != null)
            {
                this.MediaControl.StopWhenReady();
            }

            this.CurrentState = PlayState.Stopped;


            if (this.MediaEventEx != null)
            {
                this.MediaEventEx.SetNotifyWindow(IntPtr.Zero, 
                        WM_GRAPHNOTIFY, 
                        IntPtr.Zero);
            }


            if (this.VideoWindow != null)
            {
                this.VideoWindow.put_Visible(OABool.False);
                this.VideoWindow.put_Owner(IntPtr.Zero);
            }


            if (rot != null)
            {
                rot.Dispose();
                rot = null;
            }


            Marshal.ReleaseComObject(this.MediaControl);
            Marshal.ReleaseComObject(this.MediaEventEx);
            Marshal.ReleaseComObject(this.VideoWindow);
            Marshal.ReleaseComObject(this.GraphBuilder);
            Marshal.ReleaseComObject(this.CaptureGraphBuilder);

            this.MediaControl = null;
            this.MediaEventEx = null;
            this.VideoWindow = null;
            this.CaptureGraphBuilder = null;
            this.GraphBuilder = null;
        }



        public void HandleGraphEvent()
        {
            int hr = 0;
            EventCode evCode;
            int evParam1;
            int evParam2;

            if (MediaEventEx == null)
            {
                return;
            }

            while (MediaEventEx.GetEvent(out evCode, out evParam1, out evParam2, 0) == 0)
            {
                hr = MediaEventEx.FreeEventParams(evCode, evParam1, evParam2);
            }
        }

        public IBaseFilter FindCaptureDevice()
        {

            int hr = 0;
            IEnumMoniker IclassEnum;
            System.Runtime.InteropServices.UCOMIEnumMoniker classEnum;

            IMoniker[] moniker = new IMoniker[1];

            Object source = null;
            ICreateDevEnum devEnum = (ICreateDevEnum)(new CreateDevEnum());

            hr = devEnum.CreateClassEnumerator(FilterCategory.VideoInputDevice,
                out classEnum, 0);


            IclassEnum = (IEnumMoniker)(classEnum);

            Marshal.ReleaseComObject(devEnum);

            if (classEnum == null)
            {
                throw new ApplicationException("No device video on board.");
            }
            if (IclassEnum.Next(moniker.Length, moniker, IntPtr.Zero) == 0)
            {
                Guid iid = typeof(IBaseFilter).GUID;
                moniker[0].BindToObject(null, null, iid, out source);
            }
            else
            {
                throw new ApplicationException("Unable to access video capture device!");
            }
            Marshal.ReleaseComObject(moniker[0]);
            Marshal.ReleaseComObject(classEnum);
            return (IBaseFilter)(source);
        }


        public void ChangePreviewState(bool showVideo)
        {
            int hr = 0;

            if (this.MediaControl == null)
            {
                return;
            }
            if (showVideo == true)
            {
                if (this.CurrentState != PlayState.Running)
                {
                    hr = this.MediaControl.Run();
                    this.CurrentState = PlayState.Running;
                }
            }
            else
            {

                hr = this.MediaControl.StopWhenReady();
                this.CurrentState = PlayState.Stopped;
            }
        }

        public void ResizeVideoWindow(HandledObject ho)
        {
            if (VideoWindow != null)
            {
                VideoWindow.SetWindowPosition(0, 0, ho.width, ho.clientSize.Height);
            }
        }
    }
}



Questo è l'oggetto che sostituisce e wrappa tutte le attività lasciando libero e snello il form.
Il motivo è semplice, in questo modo posso aggiungere una picturebox o qualsiasi altro oggetto per cui sussistano dimensioni e handle, mapparlo nell'oggetto di scambio, e gestire così la camera.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using DirectShowLib;
using System.Windows.Forms;
using CameraCapture.Objects;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
namespace CameraCapture
{
    public partial class frmMain : Form
    {
        DirectShowWrapper dsw = new DirectShowWrapper();
        HandledObject ho = new HandledObject();

      
        public frmMain()
        {            
            InitializeComponent();

            ho.height = this.Height;
            ho.width = this.Width;
            ho.handle = this.Handle;
            ho.clientSize = this.ClientSize;

            dsw.CaptureVideo(ho);
        }


        protected void WndProc(Message m)
        {
            if (m.Msg == dsw.WM_GRAPHNOTIFY)
            {
                dsw.HandleGraphEvent();
            }

            if (dsw.VideoWindow != null)
            {
                dsw.VideoWindow.NotifyOwnerMessage(
                                m.HWnd,
                                m.Msg,
                                (int)m.WParam,
                                (int)m.LParam);
            }
            else
            {
                base.WndProc(ref m);
            }
        }


        private void frmMain_Resize(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Minimized)
                dsw.ChangePreviewState(false);

            if (this.WindowState == FormWindowState.Normal)
                dsw.ChangePreviewState(true);

            ho.height = this.Height;
            ho.width = this.Width;
            ho.handle = this.Handle;
            ho.clientSize = this.ClientSize;

            dsw.ResizeVideoWindow(ho);
        }

        public void frmMain_FormClosed(object sender, FormClosedEventArgs e)
        {
            dsw.closeinterfaces();
        }

    
    }
}



Orbene questo è quanto rimane del form ...ora la situazione è sicuramente molto più gestibile e pulita.

mercoledì 29 maggio 2013

How TO: C# internal WEB CAM

Ho cercato in lungo e in largo qualcosa di UTILIZZABILE e facilmente documentabile per creare un applicazione C# che sia in grado di utilizzare la WEBcam interna..

Ammetto che non c'e' molto ( c'è tanto ma nulla come lo cercavo io ) se non qualche esempio con Wia, o librerie create da qualcuno di cui non sempre si sa la provenienza.


Questo listato .. frutto di una traduzione da VB.Net, mi ha dato un buon risultato, e ammetto che paga. E' veloce, decisamente snello non semplicissimo da leggere.


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using DirectShowLib;
using System.Windows.Forms;
using CameraCapture.Objects;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
namespace CameraCapture
{
    public partial class frmMain : Form
    {

        public int D = Convert.ToInt32("0X8000", 16);

        public int WM_GRAPHNOTIFY = 0;

        public IVideoWindow VideoWindow = null;
        public IMediaControl MediaControl = null;
        public IMediaEventEx MediaEventEx = null;
        public IGraphBuilder GraphBuilder = null;
        public ICaptureGraphBuilder2 CaptureGraphBuilder = null;

        public DsROTEntry rot = null;

        private PlayState CurrentState = PlayState.Stopped;

       

        public frmMain()
        {
            WM_GRAPHNOTIFY = D + 1;
            InitializeComponent();
            CaptureVideo(this);
        }



        protected void WndProc(Message m)
        {
            if (m.Msg == WM_GRAPHNOTIFY)
            {
                HandleGraphEvent();
            }

            if (VideoWindow != null)
            {
                VideoWindow.NotifyOwnerMessage(m.HWnd, m.Msg, 
                        (int)m.WParam, 
                        (int)m.LParam);
            }
            else
            {
                base.WndProc(ref m);
            }
        }

        public void HandleGraphEvent()
        {
            int hr = 0;
            EventCode evCode;
            int evParam1;
            int evParam2;

            if (MediaEventEx ==null) 
            {
                return;
            }

            while (MediaEventEx.GetEvent(out evCode, out evParam1, out evParam2, 0) == 0)
            {
                hr = MediaEventEx.FreeEventParams(evCode, evParam1, evParam2);            
            }
        }

        private void frmMain_FormClosed(object sender, FormClosedEventArgs e)
        {
            closeinterfaces();
        }


        public void SetupVideoWindow()
        {
            int hr = 0;

            hr = VideoWindow.put_Owner(this.Handle);


            hr = VideoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipChildren);

            ResizeVideoWindow();

            hr = VideoWindow.put_Visible(OABool.True);
        }


        private void frmMain_Resize(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Minimized )
                ChangePreviewState(false);
            
            if (this.WindowState == FormWindowState.Normal )
                ChangePreviewState(true);

            ResizeVideoWindow();
        }

        public void ResizeVideoWindow()
        {
            if (VideoWindow != null) 
            {
                VideoWindow.SetWindowPosition(0, 0, this.Width, this.ClientSize.Height);
            }
        }



        public void GetInterfaces(Form f)
        {
            int hr = 0;
            this.GraphBuilder = (IGraphBuilder)(new FilterGraph());
            this.CaptureGraphBuilder = (ICaptureGraphBuilder2)(new CaptureGraphBuilder2());
            this.MediaControl = (IMediaControl)(this.GraphBuilder);
            this.VideoWindow = (IVideoWindow)(this.GraphBuilder);
            this.MediaEventEx = (IMediaEventEx)(this.GraphBuilder);
            hr = this.MediaEventEx.SetNotifyWindow(f.Handle, WM_GRAPHNOTIFY, IntPtr.Zero);
        }


        public IBaseFilter FindCaptureDevice()
        {

            int hr = 0;
            IEnumMoniker IclassEnum;
            System.Runtime.InteropServices.UCOMIEnumMoniker classEnum;

            IMoniker[] moniker = new IMoniker[1];

            Object source = null;
            ICreateDevEnum devEnum = (ICreateDevEnum)(new CreateDevEnum());

            hr = devEnum.CreateClassEnumerator(FilterCategory.VideoInputDevice, 
                out classEnum, 0);


            IclassEnum = (IEnumMoniker)(classEnum);

            Marshal.ReleaseComObject(devEnum);

            if (classEnum == null)
            {
                throw new ApplicationException("No device video on board.");
            }
            if (IclassEnum.Next(moniker.Length, moniker, IntPtr.Zero) == 0)
            {
                Guid iid = typeof(IBaseFilter).GUID;
                moniker[0].BindToObject(null, null, iid, out source);
            }
            else
            {
                throw new ApplicationException("Unable to access video capture device!");
            }
            Marshal.ReleaseComObject(moniker[0]);
            Marshal.ReleaseComObject(classEnum);
            return (IBaseFilter)(source);
        }

        public void CaptureVideo(frmMain f)
        {
            int hr = 0;
            IBaseFilter sourceFilter = null;
            try
            {
                GetInterfaces(f);

                hr = this.CaptureGraphBuilder.SetFiltergraph(this.GraphBuilder);


                sourceFilter = FindCaptureDevice();

                hr = this.GraphBuilder.AddFilter(sourceFilter, "Video Capture");


                hr = this.CaptureGraphBuilder.RenderStream(PinCategory.Preview, 
                        MediaType.Video, 
                        sourceFilter, 
                        null, null);

                Marshal.ReleaseComObject(sourceFilter);

                f.SetupVideoWindow();

                rot = new DsROTEntry(this.GraphBuilder);

                hr = this.MediaControl.Run();

                this.CurrentState = PlayState.Running;

            }
            catch (Exception ex)
            {

            }
        }

        public void closeinterfaces()
        {

            if (this.MediaControl != null)
            {
                this.MediaControl.StopWhenReady();
            }

            this.CurrentState = PlayState.Stopped;


            if (this.MediaEventEx != null)
            {
                this.MediaEventEx.SetNotifyWindow(IntPtr.Zero, WM_GRAPHNOTIFY, IntPtr.Zero);
            }


            if (this.VideoWindow != null)
            {
                this.VideoWindow.put_Visible(OABool.False);
                this.VideoWindow.put_Owner(IntPtr.Zero);
            }


            if (rot != null)
            {
                rot.Dispose();
                rot = null;
            }


            Marshal.ReleaseComObject(this.MediaControl);
            Marshal.ReleaseComObject(this.MediaEventEx);
            Marshal.ReleaseComObject(this.VideoWindow);
            Marshal.ReleaseComObject(this.GraphBuilder);
            Marshal.ReleaseComObject(this.CaptureGraphBuilder);

            this.MediaControl = null;
            this.MediaEventEx = null;
            this.VideoWindow = null;
            this.CaptureGraphBuilder = null;
            this.GraphBuilder = null;
        }

        public void ChangePreviewState(bool showVideo)
        {
            int hr = 0;

            if (this.MediaControl == null)
            {
                return;
            }
            if (showVideo == true)
            {
                if (this.CurrentState != PlayState.Running)
                {
                    hr = this.MediaControl.Run();
                    this.CurrentState = PlayState.Running;
                }
            }
            else
            {

                hr = this.MediaControl.StopWhenReady();
                this.CurrentState = PlayState.Stopped;
            }
        }
    }
}

E questo è l'enumerativo.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CameraCapture.Objects
{
    public enum PlayState
    {
        Stopped,
        Paused,
        Running,
        Init
    }
}





L'unica notazione è l'aggiunta della libreria di DirectShow.


Il resto è solo divertimento .. o sperimentazione:


... E buon prò vi faccia come al solito !!