protected override void OnMuxing(object sender, DownloadCompletedEventArgs e)
        {
            // Separate file extension.
            DownloadItemData IData = e.DownloadInfo.Data as DownloadItemData;

            FileProgress     VideoFile = e.DownloadInfo.Files.FirstOrDefault(f => f.Type == StreamType.Video);
            FileProgress     AudioFile = e.DownloadInfo.Files.FirstOrDefault(f => f.Type == StreamType.Audio);
            string           SrcFile   = IData.Media.FileName != null ? Settings.NaturalGroundingFolder + IData.Media.FileName : null;
            CompletionStatus Result    = CompletionStatus.Success;

            if (IData.Media.FileName != null && File.Exists(SrcFile) && (VideoFile == null || AudioFile == null))
            {
                // Upgrade audio or video
                FFmpegProcess MInfo       = MediaInfo.GetFileInfo(SrcFile);
                string        VideoFormat = VideoFile != null?Path.GetExtension(VideoFile.Destination).TrimStart('.') : MInfo.VideoStream?.Format;

                string AudioFormat = AudioFile != null?Path.GetExtension(AudioFile.Destination).TrimStart('.') : MInfo.AudioStream?.Format;

                string VideoDestExt = GetFinalExtension(VideoFormat, AudioFormat);
                e.DownloadInfo.Destination = e.DownloadInfo.DestinationNoExt + VideoDestExt;
                Result = MediaMuxer.Muxe(VideoFile?.Destination ?? SrcFile, AudioFile?.Destination ?? SrcFile, e.DownloadInfo.Destination);
            }
            if (Result == CompletionStatus.Success && File.Exists(SrcFile))
            {
                FileOperationAPIWrapper.MoveToRecycleBin(SrcFile);
            }

            e.DownloadInfo.Status = Result == CompletionStatus.Success ? DownloadStatus.Done : DownloadStatus.Failed;
        }
        protected override void OnCompleted(object sender, DownloadCompletedEventArgs e)
        {
            DownloadItemData IData          = e.DownloadInfo.Data as DownloadItemData;
            Media            Video          = IData.Media;
            string           Destination    = e.DownloadInfo.Destination;
            string           DestinationExt = Path.GetExtension(Destination);

            Destination = Destination.Substring(0, Destination.Length - Path.GetExtension(Destination).Length);

            // Ensure download and merge succeeded.
            if (!FileHasContent(e.DownloadInfo.Destination))
            {
                e.DownloadInfo.Status = DownloadStatus.Failed;
                return;
            }

            // Get final file name.
            DefaultMediaPath PathCalc    = new DefaultMediaPath();
            string           NewFileName = PathCalc.GetDefaultFileName(Video.Artist, Video.Title, Video.MediaCategoryId, (MediaType)Video.MediaTypeId);

            Directory.CreateDirectory(Path.GetDirectoryName(Settings.NaturalGroundingFolder + NewFileName));
            Video.FileName = NewFileName + DestinationExt;

            // Move file and overwrite.
            string DstFile = Settings.NaturalGroundingFolder + Video.FileName;

            if (File.Exists(DstFile))
            {
                FileOperationAPIWrapper.MoveToRecycleBin(DstFile);
            }
            File.Move(Destination + DestinationExt, DstFile);

            // Add to database
            EditVideoBusiness Business     = new EditVideoBusiness();
            Media             ExistingData = Business.GetVideoById(Video.MediaId);

            if (ExistingData != null)
            {
                // Edit video info.
                ExistingData.FileName = Video.FileName;
                ExistingData.Length   = null;
                ExistingData.Height   = null;
                Business.Save();
            }
            else
            {
                // Add new video info.
                Business.AddVideo(Video);
                Business.Save();
            }

            base.OnCompleted(sender, e);
        }
        /// <summary>
        /// Occurs when download is completed.
        /// </summary>
        private async void Download_Complete(object sender, DownloadCompletedEventArgs args)
        {
            DownloadItemData IData = args.DownloadInfo.Data as DownloadItemData;

            if (args.DownloadInfo.IsCompleted && (IData.QueuePos == 0 || player.CurrentVideo == null) && !player.AllowClose)
            {
                nextVideo = IData.Media;
                player_PlayNext(null, null);
            }
            else if (args.DownloadInfo.IsCanceled && IData.QueuePos > -1 && playMode != PlayerMode.Manual)
            {
                nextVideo = null;
                await SelectNextVideoAsync(IData.QueuePos, false).ConfigureAwait(false);
            }
        }
        /// <summary>
        /// Plays the next video.
        /// </summary>
        private async Task PlayNextVideoAsync()
        {
            if (nextVideo == null)
            {
                return;
            }

            // Enable/Disable SVP if necessary.
            MpcConfigBusiness.AutoConfigure(nextVideo);

            // If next video is still downloading, advance QueuePos. If QueuePos = 0 when download finishes, it will auto-play.
            var VideoDownload = GetNextVideoDownloading();

            if (VideoDownload != null)
            {
                DownloadItemData IData = VideoDownload.Data as DownloadItemData;
                if (IData.QueuePos > 0)
                {
                    IData.QueuePos--;
                }
                return;
            }

            // Auto-pitch to 432hz
            bool EnableAutoPitch = AutoPitchBusiness.AppyAutoPitch(nextVideo);

            await player.PlayVideoAsync(nextVideo, EnableAutoPitch).ConfigureAwait(false);

            playedVideos.Add(nextVideo.MediaId);
            nextVideo = null;

            if (PlayMode == PlayerMode.SpecialRequest)
            {
                PlayMode = PlayerMode.Normal;
            }

            if (playMode != PlayerMode.Manual)
            {
                await SelectNextVideoAsync(1, false).ConfigureAwait(false);
            }

            if (PlayMode == PlayerMode.Fire)
            {
                PlayMode = PlayerMode.SpecialRequest;
            }

            Application.Current.Dispatcher.Invoke(() => PlaylistChanged?.Invoke(this, new EventArgs()));
        }
        /// <summary>
        /// Cancels the download and autoplay of specified video.
        /// </summary>
        private void CancelNextDownload(Media video)
        {
            var VideoDownload = downloadManager.DownloadsList.FirstOrDefault(d => (d.Data as DownloadItemData).Media.MediaId == video.MediaId && !d.IsCompleted);

            if (VideoDownload != null)
            {
                // Removes autoplay from the next video.
                DownloadItemData IData = VideoDownload.Data as DownloadItemData;
                IData.QueuePos = -1;
                // Cancel the download if progress is less than 40%
                if (VideoDownload.ProgressValue < 40 && playMode != PlayerMode.Manual)
                {
                    VideoDownload.Status = DownloadStatus.Canceled;
                }
            }
        }