示例#1
0
 public void CopyTo(LightData destination)
 {
     destination.Time = Time;
     if (ColourData != null)
     {
         byte[] colourData = new byte[ColourData.Length];
         Buffer.BlockCopy(ColourData, 0, colourData, 0, ColourData.Length);
         destination.ColourData = colourData;
     }
 }
 /// <summary>
 /// Thread safe retrieval of the previous frame's final adjusted light data
 /// </summary>
 /// <returns>A copy of the current light data (can be null if no light data)</returns>
 /// <remarks>Frequent calling of this method may have a performance impact due to thread synchronisation.</remarks>
 public LightData GetPreviousLightData()
 {
     lock (previousSync)
     {
         if (_prevLightData == null)
         {
             return(null);
         }
         LightData data = new LightData(_prevLightData);
         return(data);
     }
 }
        private void OutputLoop()
        {
            try
            {
                //Get Light Setup Plugin
                ILightSetupPlugin lightSetupPlugin = CurrentProfile.LightSetupPlugin;

                Stopwatch timer     = new Stopwatch();
                double    waitTicks = 1.0 / CurrentProfile.OutputFrequency;
                double    freq      = 1.0 / Stopwatch.Frequency;

                long lastUpdate = 0;

                // Initialise temporary lightData
                LightData lightData = new LightData(lightSetupPlugin.Lights.Count);

                while (Active)
                {
                    timer.Restart();

                    // If available, replace _currentLightData with _nextLightData
                    lock (sync)
                    {
                        if (lastUpdate < _nextLightData.Time)
                        {
                            var t = lightData;
                            lightData      = _nextLightData;
                            _nextLightData = t;
                            lastUpdate     = lightData.Time;
                        }
                    }

                    if (lightData != null)
                    {
                        // Run pre-output plugins
                        CurrentProfile.PreOutputPlugins.ToList().ForEach(po => po.PreOutput(lightSetupPlugin.Lights, lightData));

                        //Run Output Plugin(s)
                        CurrentProfile.OutputPlugins.ToList().ForEach(o => o.Output(lightSetupPlugin.Lights, lightData));
                    }

                    // Copy the last frame to _prevLightData
                    lock (previousSync)
                    {
                        Buffer.BlockCopy(lightData.ColourData, 0, _prevLightData.ColourData, 0, lightData.ColourData.Length);
                    }

                    // Throttle Output Frequency
                    while (timer.ElapsedTicks * freq < waitTicks)
                    {
                        Task.Delay(5);
                    }

                    _outputLoopFPS.Tick();
                }
            }
            catch (Exception e)
            {
                lock (sync)
                {
                    Active = false;
                    AfterglowRuntime.Logger.Error(e, "Afterglow Runtime - Output Loop");
                }
            }
            finally
            {
                // Allow plugins to clean up
                CurrentProfile.PreOutputPlugins.ForEach(po => po.Stop());
                CurrentProfile.OutputPlugins.ForEach(o => o.Stop());
            }
        }
        private void CaptureLoop()
        {
            try
            {
                //Get Light Setup Plugin
                ILightSetupPlugin lightSetupPlugin = CurrentProfile.LightSetupPlugin;

                Stopwatch timer     = Stopwatch.StartNew();
                long      lastTicks = 0;
                double    waitTicks = 1.0 / CurrentProfile.CaptureFrequency;
                double    freq      = 1.0 / Stopwatch.Frequency;

                LightData newLightData = new LightData(_nextLightData);

                while (Active)
                {
                    lastTicks = timer.ElapsedTicks;

                    //Get screen segments
                    IDictionary <Light, PixelReader> ledSources = CurrentProfile.CapturePlugin.Capture(lightSetupPlugin);
                    newLightData.Time = timer.ElapsedTicks;
                    try
                    {
                        //Extract Colours from segments
                        int i = 0;
                        foreach (var keyValue in ledSources)
                        {
                            newLightData[i] = CurrentProfile.ColourExtractionPlugin.Extract(keyValue.Key, keyValue.Value);
                            i++;
                        }
                    }
                    finally
                    {
                        //Dispose of screen segments
                        foreach (var keyValue in ledSources)
                        {
                            keyValue.Value.Dispose();
                        }

                        //Dispose of whole screen
                        CurrentProfile.CapturePlugin.ReleaseCapture();
                    }

                    //Run any Post Process Plugins
                    foreach (var postProcessPlugin in CurrentProfile.PostProcessPlugins)
                    {
                        (postProcessPlugin as IPostProcessPlugin).Process(lightSetupPlugin.Lights, newLightData);
                    }

                    // Thread safe swap of new light data into _nextLightData
                    lock (sync)
                    {
                        var t = _nextLightData;
                        _nextLightData = newLightData;
                        newLightData   = t;
                    }

                    // Throttle Capture Frequency
                    while ((timer.ElapsedTicks - lastTicks) * freq < waitTicks)
                    {
                        Task.Delay(5);
                    }

                    // Update capture FPS counter
                    _captureLoopFPS.Tick();
                }
            }
            catch (Exception e)
            {
                lock (sync)
                {
                    Active = false;
                    AfterglowRuntime.Logger.Error(e, "Afterglow Runtime - Capture Loop");
                }
            }
            finally
            {
                // Allow plugins to clean up
                CurrentProfile.CapturePlugins.ForEach(cp => cp.Stop());
                CurrentProfile.PostProcessPlugins.ForEach(pp => pp.Stop());
            }
        }
        /// <summary>
        /// Start running the current profile
        /// </summary>
        public void Start()
        {
            Stop();
            Logger.Info("Starting...");

            bool profileJustSet = false;

            if (this.CurrentProfile == null)
            {
                this.CurrentProfile = (from p in this.Setup.Profiles
                                       where p.Id == this.Setup.CurrentProfileId
                                       select p).FirstOrDefault();
                profileJustSet = true;
            }

            if (this.CurrentProfile == null)
            {
                CurrentProfile = this.Setup.Profiles.FirstOrDefault();
                profileJustSet = true;
            }

            if (CurrentProfile == null)
            {
                Logger.Error("No profile has been selected");
                return;
            }
            else
            {
                //Reset current profile incase there has been any setting changes
                if (!profileJustSet)
                {
                    this.CurrentProfile = (from p in this.Setup.Profiles
                                           where p.Id == this.CurrentProfile.Id
                                           select p).First();
                }

                CurrentProfile.Validate();

                if (!Active)
                {
                    Active = true;

                    // Prepare light data buffer
                    _nextLightData = new LightData(CurrentProfile.LightSetupPlugin.Lights.Count);
                    _prevLightData = new LightData(CurrentProfile.LightSetupPlugin.Lights.Count);;

                    // Start all plugins
                    CurrentProfile.CapturePlugin.Start();
                    CurrentProfile.ColourExtractionPlugin.Start();
                    CurrentProfile.PostProcessPlugins.ToList().ForEach(p => p.Start());
                    CurrentProfile.PreOutputPlugins.ToList().ForEach(p => p.Start());

                    string errorMessage   = String.Empty;
                    int    outputFailures = 0;
                    List <IOutputPlugin> outputPluginsInError = new List <IOutputPlugin>();
                    foreach (IOutputPlugin outputPlugin in CurrentProfile.OutputPlugins)
                    {
                        if (!outputPlugin.TryStart())
                        {
                            outputFailures++;
                            outputPluginsInError.Add(outputPlugin);
                        }
                    }

                    //If all output plugins are in error then stop
                    if (outputFailures == CurrentProfile.OutputPlugins.Count())
                    {
                        Stop();
                    }
                    else
                    {
                        //Remove plugins in error and allow other plugins to continue to run
                        outputPluginsInError.ForEach(o => this.CurrentProfile.OutputPlugins.Remove(o));

                        // Commence capture and output threads
                        _captureLoopTask = Task.Factory.StartNew(CaptureLoop);
                        _outputLoopTask  = Task.Factory.StartNew(OutputLoop);
                    }
                }
            }
        }
示例#6
0
 public LightData(LightData copyFrom)
 {
     copyFrom.CopyTo(this);
 }