/// <summary>
        /// Send any queued outputs inclusively inside the specified range.
        /// Queued outputs less than the minimum will be dropped.
        /// Setting the maximum to -1 will re-enable output (same as 'EnableOutput = true') and
        /// send all queued outputs.
        /// </summary>
        /// <param name="MinimumChunkIndex">Inclusive minimum chunk to send</param>
        /// <param name="MaximumChunkIndex">Inclusive maximum chunk to send</param>
        /// <remarks>To enable output while clearing all queued outputs, call as 'SendOutput(Job.SegmentNumber, -1)'</remarks>
        public void SendOutput(int MinimumChunkIndex, int MaximumChunkIndex)
        {
            lock (SyncLock) {
                int max = (MaximumChunkIndex >= 0) ? (MaximumChunkIndex) : (int.MaxValue);

                int jobs_to_run = 0;                 // number of output workers to start.

                List <ChunkDetail> chunks_waiting = ChunksCompleted.ToList();
                chunks_waiting.Sort((a, b) => a.ChunkIndex.CompareTo(b.ChunkIndex));

                ChunksCompleted.Clear();
                foreach (var chunk in chunks_waiting)
                {
                    if (chunk.ChunkIndex > max)
                    {
                        ChunksCompleted.Enqueue(chunk);
                        continue;
                    }

                    if (chunk.ChunkIndex >= MinimumChunkIndex)
                    {
                        jobs_to_run++;                         // note another job to be run.
                        ChunksCompleted.Enqueue(chunk);
                    }
                    else
                    {
                        // drop this file.
                        FilesCompleted.Enqueue(new FileInfo(chunk.SourceFilePath));
                    }
                }

                // run jobs that are waiting and not removed.
                for (int i = 0; i < jobs_to_run; i++)
                {
                    System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(ChunkAction));
                }

                if (MaximumChunkIndex < 0)
                {
                    EnableOutput = true;
                }
            }
        }
        /// <summary>
        /// Close this output path and clean up any connections
        /// </summary>
        public void Close()
        {
            if (SelectedHandler != null)
            {
                SelectedHandler.FileConsumed -= SelectedHandler_FileConsumed;
                SelectedHandler.Close();
            }

            while (FilesCompleted.Count > 0)
            {
                FilesCompleted.Dequeue().Delete();
            }

            // clean up leftovers:
            if (ShouldCleanup)
            {
                while (ChunksCompleted.Count > 0)
                {
                    new FileInfo(ChunksCompleted.Dequeue().SourceFilePath).Delete();
                }
            }
        }
        /// <summary>
        /// Signal the output to consume the given chunk.
        /// Should only be called by the encoder.
        /// </summary>
        public void NewChunkAvailable(int ChunkIndex, int StreamIndex, double CaptureDuration)
        {
            if (SelectedHandler == null)
            {
                throw new Exception("Output handler was not initialised");
            }
            string joined     = Path.Combine(Config.EncoderSettings.LocalSystemOutputFolder, Config.EncoderSettings.LocalSystemFilePrefix);
            string chunk_path = joined + "_" + StreamIndex + "-" + ChunkIndex.ToString("00000") + ".ts";

            ChunkDetail chunk = new ChunkDetail(chunk_path, ChunkIndex, StreamIndex, CaptureDuration);

            lock (ChunksCompleted) {
                ChunksCompleted.Enqueue(chunk);
            }

            if (EnableOutput)
            {
                // Force work on a seperate thread, to prevent any interference with encoding.
                // Encoder output to local system SHOULD be unaffected by delays in output handler.
                // Final output MAY be delayed, but SHOULD be correct.
                System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(ChunkAction));
            }
        }