示例#1
0
        private void TreeView_OnSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs <object> e)
        {
            object selectedItem = e.NewValue;

            if (selectedItem == null || selectedItem is PresetFolderViewModel)
            {
                // If it's a folder that got "selected" we ignore it and leave the previous preset selected for real
                return;
            }

            if (PresetComboBox.PresetComboOpen)
            {
                // If inside a combo box the combo box binding on close will handle it.
                return;
            }

            DispatchUtilities.BeginInvoke(() =>
            {
                // This might be in the layout phase. Invoke on dispatcher to process cleanly.
                var newSelectedPreset = (PresetViewModel)selectedItem;
                if (this.presetsService.TryUpdateSelectedPreset(newSelectedPreset))
                {
                    StaticResolver.Resolve <Main>().ReadTextToScreenReader(newSelectedPreset.DisplayName);
                }
            });
        }
示例#2
0
        public PresetTreeViewContainer()
        {
            this.InitializeComponent();

            this.presetsService.PresetFolderManuallyExpanded += (sender, model) =>
            {
                var item = UIUtilities.FindDescendant <TreeViewItem>(this.presetTreeView, viewItem =>
                {
                    return(viewItem.Header == model);
                });
                //var item = this.presetTreeView.ContainerFromItem(model);

                // TODO: Find the TreeViewItem for the PresetFolderViewModel

                if (item != null)
                {
                    DispatchUtilities.BeginInvoke(
                        () =>
                    {
                        UIUtilities.BringIntoView(item);
                    },
                        DispatcherPriority.Background);
                }
            };
        }
示例#3
0
 public void RestoreWindow()
 {
     DispatchUtilities.BeginInvoke(() =>
     {
         this.Show();
         this.WindowState = this.RestoredWindowState;
     });
 }
示例#4
0
        public void Activate(string appUserModelId, string invokedArgs, NOTIFICATION_USER_INPUT_DATA[] data, uint dataCount)
        {
            StaticResolver.Resolve <Main>().RestoreWindow();

            DispatchUtilities.BeginInvoke(() =>
            {
                StaticResolver.Resolve <Main>().Activate();
            });
        }
示例#5
0
        public void Scan(string source)
        {
            var mainVM = StaticResolver.Resolve <MainViewModel>();

            DispatchUtilities.Invoke(() =>
            {
                mainVM.ScanFromAutoplay(source);
            });
        }
示例#6
0
        public void Encode(string source, string destination, string preset, string picker)
        {
            var processingService = StaticResolver.Resolve <ProcessingService>();

            DispatchUtilities.Invoke(() =>
            {
                processingService.Process(source, destination, preset, picker);
            });
        }
示例#7
0
        private void ScanNextJob()
        {
            SourcePath path = this.pathsToScan[this.currentJobIndex];

            IScanProxy scanProxy = Utilities.CreateScanProxy();

            scanProxy.ScanProgress += (sender, args) =>
            {
                lock (this.currentJobIndexLock)
                {
                    this.currentJobProgress = args.Value;
                    this.RaisePropertyChanged(nameof(this.Progress));
                }
            };

            scanProxy.ScanCompleted += (sender, args) =>
            {
                if (args.Value != null)
                {
                    JsonScanObject scanObject = JsonConvert.DeserializeObject <JsonScanObject>(args.Value);
                    this.ScanResults.Add(new ScanResult {
                        SourcePath = path, VideoSource = scanObject.ToVideoSource()
                    });
                }
                else
                {
                    this.ScanResults.Add(new ScanResult {
                        SourcePath = path
                    });
                }

                lock (this.currentJobIndexLock)
                {
                    this.currentJobIndex++;
                    this.currentJobProgress = 0;
                    this.RaisePropertyChanged(nameof(this.Progress));

                    if (this.ScanFinished)
                    {
                        DispatchUtilities.BeginInvoke(() =>
                        {
                            this.Cancel.Execute(null);
                        });
                    }
                    else
                    {
                        this.ScanNextJob();
                    }
                }
            };

            var scanLogger = StaticResolver.Resolve <AppLoggerFactory>().ResolveRemoteScanLogger(path.Path);

            scanProxy.StartScan(path.Path, scanLogger);
        }
示例#8
0
 private void ShowStatusMessage(string message)
 {
     DispatchUtilities.BeginInvoke(() =>
     {
         this.statusTextBlock.Text  = message;
         this.statusText.Visibility = Visibility.Visible;
         var storyboard             = (Storyboard)this.FindResource("StatusTextStoryboard");
         storyboard.Stop();
         storyboard.Begin();
     });
 }
示例#9
0
        public void Encode(string source, string destination, string preset, string picker)
        {
            var processingService = StaticResolver.Resolve <ProcessingService>();

            DispatchUtilities.Invoke(() =>
            {
                try
                {
                    processingService.Process(source, destination, preset, picker);
                }
                catch (Exception exception)
                {
                    throw new FaultException <AutomationError>(new AutomationError {
                        Message = exception.Message
                    });
                }
            });
        }
示例#10
0
        public void Scan(string source)
        {
            var mainVM = StaticResolver.Resolve <MainViewModel>();

            DispatchUtilities.Invoke(() =>
            {
                try
                {
                    mainVM.ScanFromAutoplay(source);
                }
                catch (Exception exception)
                {
                    throw new FaultException <AutomationError>(new AutomationError {
                        Message = exception.Message
                    });
                }
            });
        }
示例#11
0
        public void ImportQueue(string filePath)
        {
            var queueImporter = StaticResolver.Resolve <IQueueImportExport>();

            DispatchUtilities.Invoke(() =>
            {
                try
                {
                    queueImporter.Import(filePath);
                    this.ShowMessage(MainRes.QueueImportSuccessMessage);
                }
                catch (Exception)
                {
                    this.ShowMessage(MainRes.QueueImportErrorMessage);
                    throw;
                }
            });
        }
示例#12
0
        public void ImportPreset(string filePath)
        {
            var presetImporter = StaticResolver.Resolve <IPresetImportExport>();

            DispatchUtilities.Invoke(() =>
            {
                try
                {
                    Preset preset = presetImporter.ImportPreset(filePath);
                    this.ShowMessage(string.Format(MainRes.PresetImportSuccessMessage, preset.Name));
                }
                catch (Exception)
                {
                    this.ShowMessage(MainRes.PresetImportErrorMessage);
                    throw;
                }
            });
        }
示例#13
0
        private static void UpdateCornerImage(Image image, Grid imageHolder, BitmapSource bitmap, RegionChooser regionChooser, bool isRetry = false)
        {
            // Image dimensions
            int imageWidth  = bitmap.PixelWidth;
            int imageHeight = bitmap.PixelHeight;

            double availableWidth  = imageHolder.ActualWidth;
            double availableHeight = imageHolder.ActualHeight;

            if (availableWidth == 0 || availableHeight == 0)
            {
                // Intermittent bug causing this. In this case we queue it up to go again after a layout pass has been done.
                if (!isRetry)
                {
                    DispatchUtilities.BeginInvoke(() =>
                    {
                        UpdateCornerImage(image, imageHolder, bitmap, regionChooser, isRetry: true);
                    });
                }

                return;
            }

            int cornerWidthPixels  = (int)(availableWidth / ZoomedPixelSize);
            int cornerHeightPixels = (int)(availableHeight / ZoomedPixelSize);

            // Make sure the subsection of the image is not larger than the image itself
            cornerWidthPixels  = Math.Min(cornerWidthPixels, imageWidth);
            cornerHeightPixels = Math.Min(cornerHeightPixels, imageHeight);

            double cornerWidth  = cornerWidthPixels * ZoomedPixelSize;
            double cornerHeight = cornerHeightPixels * ZoomedPixelSize;

            var croppedBitmap = new CroppedBitmap();

            croppedBitmap.BeginInit();
            croppedBitmap.SourceRect = regionChooser(imageWidth, imageHeight, cornerWidthPixels, cornerHeightPixels);
            croppedBitmap.Source     = bitmap;
            croppedBitmap.EndInit();

            image.Source = croppedBitmap;
            image.Width  = cornerWidth;
            image.Height = cornerHeight;
        }
示例#14
0
        public LogWindow()
        {
            this.InitializeComponent();

            this.PopulateLogColorBrushMapping();
            this.listColumn.Width = new GridLength(Config.LogListPaneWidth);

            this.Loaded += (sender, e) =>
            {
                this.logTextBox.ScrollToEnd();
            };

            this.logCoordinator.Logs
            .Connect()
            .OnItemAdded(addedLogViewModel =>
            {
                DispatchUtilities.Invoke(() =>
                {
                    this.logCoordinator.SelectedLog = addedLogViewModel;
                    this.logsListBox.ScrollIntoView(addedLogViewModel);
                });
            })
            .Subscribe();

            this.logCoordinator.WhenAnyValue(x => x.SelectedLog).Subscribe(selectedLog =>
            {
                if (selectedLog != null)
                {
                    this.DisconnectFromLogger();
                    this.ConnectToLogger(selectedLog.Logger);
                }
            });

            this.appThemeService.AppThemeObservable.Skip(1).Subscribe(_ =>
            {
                this.Dispatcher.BeginInvoke(new Action(() =>
                {
                    this.PopulateLogColorBrushMapping();
                    this.logParagraph.Inlines.Clear();
                    this.AddExistingLogEntries();
                }));
            });
        }
示例#15
0
        public void ImportQueue(string filePath)
        {
            var queueImporter = Ioc.Get <IQueueImportExport>();

            DispatchUtilities.Invoke(() =>
            {
                try
                {
                    queueImporter.Import(filePath);
                    this.ShowMessage(MainRes.QueueImportSuccessMessage);
                }
                catch (Exception exception)
                {
                    this.ShowMessage(MainRes.QueueImportErrorMessage);
                    throw new FaultException <AutomationError>(new AutomationError {
                        Message = exception.Message
                    });
                }
            });
        }
示例#16
0
        public void ImportPreset(string filePath)
        {
            var presetImporter = Ioc.Get <IPresetImportExport>();

            DispatchUtilities.Invoke(() =>
            {
                try
                {
                    Preset preset = presetImporter.ImportPreset(filePath);
                    this.ShowMessage(string.Format(MainRes.PresetImportSuccessMessage, preset.Name));
                }
                catch (Exception exception)
                {
                    this.ShowMessage(MainRes.PresetImportErrorMessage);
                    throw new FaultException <AutomationError>(new AutomationError {
                        Message = exception.Message
                    });
                }
            });
        }
示例#17
0
        public void SetChosenTracks(List <int> chosenAudioTracks, SourceTitle selectedTitle)
        {
            DispatchUtilities.Invoke(() =>
            {
                int previousIndex = this.TargetStreamIndex;

                this.targetStreams.Clear();
                this.targetStreams.Add(new TargetStreamViewModel {
                    Text = CommonRes.All
                });

                int shownStreams = Math.Max(previousIndex, chosenAudioTracks.Count);

                for (int i = 0; i < shownStreams; i++)
                {
                    string details = null;
                    if (i < chosenAudioTracks.Count && selectedTitle != null)
                    {
                        details = selectedTitle.AudioList[chosenAudioTracks[i] - 1].Description;
                    }

                    this.targetStreams.Add(
                        new TargetStreamViewModel
                    {
                        Text         = string.Format(CommonRes.StreamChoice, (i + 1)),
                        TrackDetails = details
                    });
                }

                // Set to -1, then back to real index in order to force a refresh on the ComboBox
                this.targetStreamIndex = -1;
                this.RaisePropertyChanged(nameof(this.TargetStreamIndex));

                this.targetStreamIndex = previousIndex;
                this.RaisePropertyChanged(nameof(this.TargetStreamIndex));
            });
        }
示例#18
0
        private async void StartBackgroundUpdate()
        {
            if (this.State != UpdateState.NotStarted && this.State != UpdateState.Failed && this.State != UpdateState.UpToDate)
            {
                // Can only start updates from certain states.
                return;
            }

            this.State = UpdateState.DownloadingInfo;

            this.updateDownloadCancellationTokenSource = new CancellationTokenSource();

            await Task.Run(async() =>
            {
                try
                {
                    UpdateInfo updateInfo = await GetUpdateInfoAsync(CommonUtilities.Beta).ConfigureAwait(false);

                    if (updateInfo == null)
                    {
                        this.State = UpdateState.Failed;
                        this.logger.Log("Update download failed. Unable to get update info.");
                        return;
                    }

                    Version updateVersion = updateInfo.LatestVersion;
                    this.LatestVersion    = updateVersion;

                    if (updateVersion > Utilities.CurrentVersion)
                    {
                        // If an update is reported to be ready but the installer doesn't exist, clear out all the
                        // installer info and redownload.
                        string updateInstallerLocation = Config.UpdateInstallerLocation;
                        if (updateInstallerLocation != string.Empty && !File.Exists(updateInstallerLocation))
                        {
                            using (SQLiteTransaction transaction = Database.ThreadLocalConnection.BeginTransaction())
                            {
                                ClearUpdateMetadata();

                                transaction.Commit();
                            }

                            this.logger.Log("Downloaded update (" + updateInstallerLocation + ") could not be found. Re-downloading it.");
                        }

                        // If we have not finished the download update yet, start/resume the download.
                        if (Config.UpdateInstallerLocation == string.Empty)
                        {
                            string updateVersionText = updateVersion.ToShortString();

                            if (CommonUtilities.Beta)
                            {
                                updateVersionText += " Beta";
                            }

                            string newVersionStartedMessage = string.Format(MainRes.NewVersionDownloadStartedStatus, updateVersionText);
                            this.logger.Log(newVersionStartedMessage);

                            DispatchUtilities.BeginInvoke(() =>
                            {
                                this.logger.ShowStatus(newVersionStartedMessage);
                            });

                            this.State = UpdateState.DownloadingInstaller;
                            this.UpdateDownloadProgressFraction = 0;

                            string downloadLocation  = updateInfo.DownloadUrl;
                            string changelogLink     = updateInfo.ChangelogUrl;
                            string installerFileName = Path.GetFileName(downloadLocation);
                            string installerFilePath = Path.Combine(Utilities.UpdatesFolder, installerFileName);

                            Stream responseStream = null;
                            FileStream fileStream = null;

                            try
                            {
                                HttpClient client          = new HttpClient();
                                HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, downloadLocation);

                                long bytesProgressTotal = 0;

                                if (File.Exists(installerFilePath))
                                {
                                    var fileInfo = new FileInfo(installerFilePath);

                                    request.Headers.Range = new RangeHeaderValue(fileInfo.Length, null);
                                    bytesProgressTotal    = fileInfo.Length;

                                    fileStream = new FileStream(installerFilePath, FileMode.Append, FileAccess.Write, FileShare.None);
                                }
                                else
                                {
                                    fileStream = new FileStream(installerFilePath, FileMode.Create, FileAccess.Write, FileShare.None);
                                }

                                var response   = await client.SendAsync(request).ConfigureAwait(false);
                                responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);

                                byte[] downloadBuffer = new byte[2048];
                                int bytesRead;

                                while ((bytesRead = await responseStream.ReadAsync(downloadBuffer, 0, downloadBuffer.Length).ConfigureAwait(false)) > 0 && !this.updateDownloadCancellationTokenSource.Token.IsCancellationRequested)
                                {
                                    fileStream.Write(downloadBuffer, 0, bytesRead);
                                    bytesProgressTotal += bytesRead;

                                    this.UpdateDownloadProgressFraction = (double)bytesProgressTotal / response.Content.Headers.ContentLength.Value;
                                }

                                if (bytesRead == 0)
                                {
                                    using (SQLiteTransaction transaction = Database.ThreadLocalConnection.BeginTransaction())
                                    {
                                        Config.UpdateVersion           = updateVersion.ToString();
                                        Config.UpdateInstallerLocation = installerFilePath;
                                        Config.UpdateChangelogLocation = changelogLink;

                                        transaction.Commit();
                                    }

                                    this.State = UpdateState.InstallerReady;
                                    this.UpdateDownloadProgressFraction = 1;

                                    string message = string.Format(MainRes.NewVersionDownloadFinishedStatus, updateVersionText);
                                    this.logger.Log(message);
                                    this.logger.ShowStatus(message);
                                }
                                else
                                {
                                    // In this case the download must have been cancelled.
                                    this.State = UpdateState.NotStarted;
                                }
                            }
                            finally
                            {
                                if (responseStream != null)
                                {
                                    responseStream.Close();
                                }

                                if (fileStream != null)
                                {
                                    fileStream.Close();
                                }
                            }
                        }
                        else
                        {
                            this.State = UpdateState.InstallerReady;
                        }
                    }
                    else
                    {
                        this.State = UpdateState.UpToDate;
                    }
                }
                catch (Exception exception)
                {
                    this.State = UpdateState.Failed;
                    this.logger.Log("Update download failed: " + exception.Message);
                }
                finally
                {
                    this.updateDownloadCancellationTokenSource?.Dispose();
                    this.updateDownloadCancellationTokenSource = null;
                }
            });
        }
示例#19
0
        public PickerWindowViewModel()
        {
            using (this.autoChangeTracker.TrackAutoChange())
            {
                this.RegisterPickerProperties();

                this.pickersService.WhenAnyValue(x => x.SelectedPicker.Picker)
                .Subscribe(x =>
                {
                    using (this.autoChangeTracker.TrackAutoChange())
                    {
                        this.RaiseAllChanged();

                        // When we are swapping active pickers, update the local properties.
                        if (!this.userModifyingOutputDirectory)
                        {
                            this.OutputDirectoryOverride = this.Picker.OutputDirectoryOverride;
                        }

                        if (!this.userModifyingNameFormat)
                        {
                            this.NameFormatOverride = this.Picker.NameFormatOverride;
                        }

                        if (!this.userModifyingEncodingPreset)
                        {
                            this.PopulateEncodingPreset(this.Picker.UseEncodingPreset);
                        }
                    }
                });

                this.pickersService.WhenAnyValue(x => x.SelectedPicker.Picker.AudioLanguageCodes).Subscribe(audioLanguageCodes =>
                {
                    using (this.autoChangeTracker.TrackAutoChange())
                    {
                        this.audioLanguages.Edit(audioLanguagesInnerList =>
                        {
                            audioLanguagesInnerList.Clear();

                            if (audioLanguageCodes == null)
                            {
                                audioLanguagesInnerList.Add(new LanguageViewModel(this)
                                {
                                    Code = LanguageUtilities.GetDefaultLanguageCode()
                                });
                                return;
                            }

                            audioLanguagesInnerList.AddRange(audioLanguageCodes.Select(l => new LanguageViewModel(this)
                            {
                                Code = l
                            }));
                        });
                    }
                });

                var audioLanguagesObservable = this.audioLanguages.Connect();
                audioLanguagesObservable.Bind(this.AudioLanguagesBindable).Subscribe();
                audioLanguagesObservable.WhenAnyPropertyChanged().Subscribe(_ =>
                {
                    if (!this.autoChangeTracker.OperationInProgress)
                    {
                        this.HandleAudioLanguageUpdate();
                    }
                });

                this.pickersService.WhenAnyValue(x => x.SelectedPicker.Picker.SubtitleLanguageCodes).Subscribe(subtitleLanguageCodes =>
                {
                    using (this.autoChangeTracker.TrackAutoChange())
                    {
                        this.subtitleLanguages.Edit(subtitleLanguagesInnerList =>
                        {
                            subtitleLanguagesInnerList.Clear();

                            if (subtitleLanguageCodes == null)
                            {
                                subtitleLanguagesInnerList.Add(new LanguageViewModel(this)
                                {
                                    Code = LanguageUtilities.GetDefaultLanguageCode()
                                });
                                return;
                            }

                            subtitleLanguagesInnerList.AddRange(subtitleLanguageCodes.Select(l => new LanguageViewModel(this)
                            {
                                Code = l
                            }));
                        });
                    }
                });

                var subtitleLanguagesObservable = this.subtitleLanguages.Connect();
                subtitleLanguagesObservable.Bind(this.SubtitleLanguagesBindable).Subscribe();
                subtitleLanguagesObservable.WhenAnyPropertyChanged().Subscribe(_ =>
                {
                    if (!this.autoChangeTracker.OperationInProgress)
                    {
                        this.HandleSubtitleLanguageUpdate();
                    }
                });

                // HasMultipleAudioLanguages
                IObservable <int> audioLanguageCountObservable = audioLanguagesObservable
                                                                 .Count()
                                                                 .StartWith(this.audioLanguages.Count);
                IObservable <bool> hasMultipleAudioLanguagesObservable = audioLanguageCountObservable
                                                                         .Select(count => count > 1);
                hasMultipleAudioLanguagesObservable.ToProperty(this, x => x.HasMultipleAudioLanguages, out this.hasMultipleAudioLanguages);

                // AudioFirstTrackLabel
                hasMultipleAudioLanguagesObservable
                .Select(hasMultipleAudioLanguages =>
                {
                    return(hasMultipleAudioLanguages ? PickerRes.FirstTrackOfEachLanguageRadioButton : PickerRes.FirstTrackRadioButton);
                })
                .ToProperty(this, x => x.AudioFirstTrackLabel, out this.audioFirstTrackLabel);

                // AudioAllTracksLabel
                hasMultipleAudioLanguagesObservable
                .Select(hasMultipleAudioLanguages =>
                {
                    return(hasMultipleAudioLanguages ? PickerRes.AllTracksForTheseLanguagesRadioButton : PickerRes.AllTracksForThisLanguageRadioButton);
                })
                .ToProperty(this, x => x.AudioAllTracksLabel, out this.audioAllTracksLabel);

                // HasNoAudioLanguages
                audioLanguageCountObservable
                .Select(count => count == 0)
                .ToProperty(this, x => x.HasNoAudioLanguages, out this.hasNoAudioLanguages);

                // HasMultipleSubtitleLanguages
                IObservable <int> subtitleLanguageCountObservable = subtitleLanguagesObservable
                                                                    .Count()
                                                                    .StartWith(this.subtitleLanguages.Count);
                IObservable <bool> hasMultipleSubtitleLanguagesObservable = subtitleLanguageCountObservable
                                                                            .Select(count => count > 1);
                hasMultipleSubtitleLanguagesObservable.ToProperty(this, x => x.HasMultipleSubtitleLanguages, out this.hasMultipleSubtitleLanguages);

                // SubtitleFirstTrackLabel
                hasMultipleSubtitleLanguagesObservable
                .Select(hasMultipleSubtitleLanguages =>
                {
                    return(hasMultipleSubtitleLanguages ? PickerRes.FirstTrackOfEachLanguageRadioButton : PickerRes.FirstTrackRadioButton);
                })
                .ToProperty(this, x => x.SubtitleFirstTrackLabel, out this.subtitleFirstTrackLabel);

                // SubtitleAllTracksLabel
                hasMultipleSubtitleLanguagesObservable
                .Select(hasMultipleSubtitleLanguages =>
                {
                    return(hasMultipleSubtitleLanguages ? PickerRes.AllTracksForTheseLanguagesRadioButton : PickerRes.AllTracksForThisLanguageRadioButton);
                })
                .ToProperty(this, x => x.SubtitleAllTracksLabel, out this.subtitleAllTracksLabel);

                // HasNoSubtitleLanguages
                subtitleLanguageCountObservable
                .Select(count => count == 0)
                .ToProperty(this, x => x.HasNoSubtitleLanguages, out this.hasNoSubtitleLanguages);

                // SubtitleQuantityClass
                this.WhenAnyValue(x => x.SubtitleSelectionMode, x => x.SubtitleIndices, x => x.HasMultipleSubtitleLanguages, x => x.SubtitleLanguageAll, (selectionMode, subtitleIndices, hasMultipleLanguages, subtitleLanguageAll) =>
                {
                    switch (selectionMode)
                    {
                    case SubtitleSelectionMode.Disabled:
                    case SubtitleSelectionMode.None:
                        return(SubtitleQuantityClass.None);

                    case SubtitleSelectionMode.First:
                    case SubtitleSelectionMode.ForeignAudioSearch:
                        return(SubtitleQuantityClass.Single);

                    case SubtitleSelectionMode.ByIndex:
                        return(ParseUtilities.ParseCommaSeparatedListToPositiveIntegers(subtitleIndices).Count > 1 ? SubtitleQuantityClass.Multiple : SubtitleQuantityClass.Single);

                    case SubtitleSelectionMode.Language:
                        if (hasMultipleLanguages)
                        {
                            return(SubtitleQuantityClass.Multiple);
                        }

                        return(subtitleLanguageAll ? SubtitleQuantityClass.Multiple : SubtitleQuantityClass.Single);

                    case SubtitleSelectionMode.All:
                        return(SubtitleQuantityClass.Multiple);

                    default:
                        throw new ArgumentOutOfRangeException(nameof(selectionMode), selectionMode, null);
                    }
                }).ToProperty(this, x => x.SubtitleQuantityClass, out this.subtitleQuantityClass);

                // ShowMarkFirstAsDefaultCheckBox
                this.WhenAnyValue(x => x.SubtitleQuantityClass, x => x.SubtitleSelectionMode, (subtitleQuantityClass, selectionMode) =>
                {
                    return(subtitleQuantityClass == SubtitleQuantityClass.Multiple && selectionMode != SubtitleSelectionMode.ByIndex);
                }).ToProperty(this, x => x.ShowMarkFirstAsDefaultCheckBox, out this.showMarkFirstAsDefaultCheckBox);

                this.pickersService.WhenAnyValue(x => x.SelectedPicker.Picker.IsDefault, x => x.SelectedPicker.Picker.IsModified, (isDefault, isModified) => !isDefault && !isModified).ToProperty(this, x => x.DeleteButtonVisible, out this.deleteButtonVisible);

                this.pickersService.WhenAnyValue(x => x.SelectedPicker.Picker.DisplayName, x => x.SelectedPicker.Picker.IsModified, (displayName, isModified) =>
                {
                    string windowTitle2 = string.Format(PickerRes.WindowTitle, displayName);
                    if (isModified)
                    {
                        windowTitle2 += " *";
                    }

                    return(windowTitle2);
                }).ToProperty(this, x => x.WindowTitle, out this.windowTitle);

                // Whenever the output directory override is disabled, used the config.
                this.WhenAnyValue(x => x.OutputDirectoryOverrideEnabled).Subscribe(directoryOverrideEnabled =>
                {
                    if (!directoryOverrideEnabled)
                    {
                        this.OutputDirectoryOverride = Config.AutoNameOutputFolder;
                    }
                    else
                    {
                        this.OutputDirectoryOverride = this.Picker.OutputDirectoryOverride;
                    }
                });

                // Whenever the name format override is disabled, used the config.
                this.WhenAnyValue(x => x.NameFormatOverrideEnabled).Subscribe(nameFormatOverrideEnabled =>
                {
                    if (!nameFormatOverrideEnabled)
                    {
                        this.NameFormatOverride = AutoNameCustomFormat;
                    }
                    else
                    {
                        this.NameFormatOverride = this.Picker.NameFormatOverride;
                    }
                });

                // Whenever UseEncodingPreset is false, set the selected VM to null.
                this.WhenAnyValue(x => x.UseEncodingPreset).Subscribe(useEncodingPreset => { this.PopulateEncodingPreset(useEncodingPreset); });

                // Update the underlying picker when our local properties change.
                // Don't need to raise another changed event as our local property setter already raises it.
                this.WhenAnyValue(x => x.OutputDirectoryOverride).Skip(1).Subscribe(directoryOverride =>
                {
                    this.userModifyingOutputDirectory = true;
                    this.UpdatePickerProperty(nameof(this.Picker.OutputDirectoryOverride), directoryOverride, raisePropertyChanged: false);
                    this.outputPathService.GenerateOutputFileName();
                    this.userModifyingOutputDirectory = false;
                });

                this.WhenAnyValue(x => x.NameFormatOverride).Skip(1).Subscribe(nameFormatOverride =>
                {
                    this.userModifyingNameFormat = true;
                    this.UpdatePickerProperty(nameof(this.Picker.NameFormatOverride), nameFormatOverride, raisePropertyChanged: false);
                    this.outputPathService.GenerateOutputFileName();
                    this.userModifyingNameFormat = false;
                });

                this.WhenAnyValue(x => x.SelectedPreset).Subscribe(selectedPreset =>
                {
                    this.userModifyingEncodingPreset = true;
                    string presetName = selectedPreset == null ? null : selectedPreset.Preset.Name;
                    this.UpdatePickerProperty(nameof(this.Picker.EncodingPreset), presetName, raisePropertyChanged: false);
                    if (this.UseEncodingPreset && selectedPreset != null)
                    {
                        if (!this.PresetsService.TryUpdateSelectedPreset(selectedPreset))
                        {
                            DispatchUtilities.BeginInvoke(() =>
                            {
                                this.SelectedPreset = this.PresetsService.SelectedPreset;
                            });
                        }
                    }

                    this.userModifyingEncodingPreset = false;
                });
            }
        }
示例#20
0
        public bool TryUpdateSelectedPreset(PresetViewModel value)
        {
            if (value == null || this.selectedPreset == value)
            {
                return(false);
            }

            PresetViewModel previouslySelectedPreset = this.selectedPreset;
            bool            changeSelectedPreset     = true;

            if (this.selectedPreset != null && this.selectedPreset.Preset.IsModified)
            {
                string           dialogMessage;
                string           dialogTitle;
                MessageBoxButton buttons;

                if (this.selectedPreset.Preset.IsBuiltIn)
                {
                    dialogMessage = MainRes.PresetDiscardConfirmMessage;
                    dialogTitle   = MainRes.PresetDiscardConfirmTitle;
                    buttons       = MessageBoxButton.OKCancel;
                }
                else
                {
                    dialogMessage = MainRes.SaveChangesPresetMessage;
                    dialogTitle   = MainRes.SaveChangesPresetTitle;
                    buttons       = MessageBoxButton.YesNoCancel;
                }

                MessageBoxResult dialogResult = Utilities.MessageBox.Show(
                    this.main,
                    dialogMessage,
                    dialogTitle,
                    buttons);
                if (dialogResult == MessageBoxResult.Yes)
                {
                    // Yes, we wanted to save changes
                    this.SavePreset();
                }
                else if (dialogResult == MessageBoxResult.No || dialogResult == MessageBoxResult.OK)
                {
                    // No, we didn't want to save changes or OK, we wanted to discard changes.
                    this.RevertPreset(userInitiated: false);
                }
                else if (dialogResult == MessageBoxResult.Cancel)
                {
                    // Queue up an action to switch back to this preset.
                    int currentPresetIndex = this.AllPresets.IndexOf(this.selectedPreset);

                    DispatchUtilities.BeginInvoke(() =>
                    {
                        this.SelectedPreset = this.AllPresets[currentPresetIndex];
                    });

                    changeSelectedPreset = false;
                }
            }

            this.selectedPreset            = value;
            this.selectedPreset.IsSelected = true;             // For TreeView

            if (changeSelectedPreset)
            {
                this.NotifySelectedPresetChanged();

                if (previouslySelectedPreset != null)
                {
                    Config.LastPresetIndex = this.AllPresets.IndexOf(this.selectedPreset);
                }

                // If we're switching away from a temporary queue preset, remove it.
                if (previouslySelectedPreset != null && previouslySelectedPreset.Preset.IsQueue && previouslySelectedPreset != value)
                {
                    this.AllPresets.Remove(previouslySelectedPreset);
                }
            }

            return(changeSelectedPreset);
        }
示例#21
0
 private void HandleDiscEvent(object sender, EventArrivedEventArgs e)
 {
     DispatchUtilities.BeginInvoke(() => this.mainViewModel.UpdateDriveCollection());
 }
示例#22
0
        public static void SetVideo(this IPreviewFrame previewFrame, Action onCompleted, Action onFailed, IObservable <double> volume)
        {
            Grid holder = previewFrame.Holder;

            if (HasChild <MediaElement>(holder))
            {
                // There is already a video in here.
                RemoveImage(holder);
                return;
            }

            // Close any video that was there before.
            RemoveVideo(holder);

            // Add on a new video
            var mediaElement = new MediaElement
            {
                Stretch = Stretch.Fill,
                Opacity = 0
            };

            var viewModel = (PreviewWindowViewModel)previewFrame.Holder.DataContext;

            mediaElement.SetBinding(MediaElement.SourceProperty, nameof(viewModel.PreviewFilePath));
            mediaElement.LoadedBehavior   = MediaState.Manual;
            mediaElement.ScrubbingEnabled = true;
            mediaElement.MediaOpened     += (sender, args) =>
            {
                if (mediaElement.NaturalDuration.HasTimeSpan)
                {
                    viewModel.PreviewVideoDuration = mediaElement.NaturalDuration.TimeSpan;
                }
                else
                {
                    viewModel.PreviewVideoDuration = TimeSpan.Zero;
                }

                // Video starts out black so we want to hold it at the start until it displays fully.
                mediaElement.Pause();

                DispatchUtilities.BeginInvoke(() =>
                {
                    OnVideoPlaying(holder);
                    mediaElement.Play();
                });
            };

            mediaElement.MediaFailed += (sender, args) =>
            {
                onFailed();
            };

            mediaElement.MediaEnded += (sender, args) =>
            {
                onCompleted();
            };

            volume.Subscribe(v =>
            {
                mediaElement.Volume = v;
            });

            mediaElement.Play();

            holder.Children.Add(mediaElement);
        }
示例#23
0
        public Main()
        {
            Ioc.Container.RegisterSingleton <Main>(() => this);
            this.InitializeComponent();

            this.sourceRow.Height = new GridLength(Config.SourcePaneHeightStar, GridUnitType.Star);
            this.queueRow.Height  = new GridLength(Config.QueuePaneHeightStar, GridUnitType.Star);

            this.Activated += (sender, args) =>
            {
                DispatchUtilities.BeginInvoke(async() =>
                {
                    // Need to yield here for some reason, otherwise the activation is blocked.
                    await Task.Yield();
                    this.toastNotificationService.Clear();
                });
            };

            this.notifyIcon = new NotifyIcon
            {
                Visible = false
            };
            this.notifyIcon.Click       += (sender, args) => { this.RestoreWindow(); };
            this.notifyIcon.DoubleClick += (sender, args) => { this.RestoreWindow(); };

            StreamResourceInfo streamResourceInfo = System.Windows.Application.GetResourceStream(new Uri("pack://application:,,,/VidCoder_icon.ico"));

            if (streamResourceInfo != null)
            {
                Stream iconStream = streamResourceInfo.Stream;
                this.notifyIcon.Icon = new Icon(iconStream);
            }

            this.RefreshQueueColumns();
            this.LoadCompletedColumnWidths();

#if DEBUG
            var debugDropDown = new DropDownButton {
                Header = "Debug"
            };

            var loadScanFromJsonItem = new Fluent.MenuItem {
                Header = "Load scan from JSON..."
            };
            loadScanFromJsonItem.Click += (sender, args) =>
            {
                DebugJsonDialog dialog = new DebugJsonDialog("Debug Scan JSON");
                dialog.ShowDialog();
                if (!string.IsNullOrWhiteSpace(dialog.Json))
                {
                    try
                    {
                        var scanObject = JsonConvert.DeserializeObject <JsonScanObject>(dialog.Json);
                        this.viewModel.UpdateFromNewVideoSource(new VideoSource {
                            Titles = scanObject.TitleList, FeatureTitle = scanObject.MainFeature
                        });
                    }
                    catch (Exception exception)
                    {
                        MessageBox.Show(this, "Could not parse scan JSON:" + Environment.NewLine + Environment.NewLine + exception.ToString());
                    }
                }
            };
            debugDropDown.Items.Add(loadScanFromJsonItem);

            var queueFromJsonItem = new Fluent.MenuItem {
                Header = "Queue job from JSON..."
            };
            queueFromJsonItem.Click += (sender, args) =>
            {
                if (!this.viewModel.HasVideoSource)
                {
                    StaticResolver.Resolve <IMessageBoxService>().Show("Must open source before adding queue job from JSON");
                    return;
                }

                EncodeJobViewModel jobViewModel = this.viewModel.CreateEncodeJobVM();
                DebugJsonDialog    dialog       = new DebugJsonDialog("Debug Encode JSON");
                dialog.ShowDialog();

                if (!string.IsNullOrWhiteSpace(dialog.Json))
                {
                    try
                    {
                        JsonEncodeObject encodeObject = JsonConvert.DeserializeObject <JsonEncodeObject>(dialog.Json);

                        jobViewModel.DebugEncodeJsonOverride = dialog.Json;
                        jobViewModel.Job.FinalOutputPath     = encodeObject.Destination.File;
                        jobViewModel.Job.SourcePath          = encodeObject.Source.Path;

                        this.processingService.Queue(jobViewModel);
                    }
                    catch (Exception exception)
                    {
                        MessageBox.Show(this, "Could not parse encode JSON:" + Environment.NewLine + Environment.NewLine + exception.ToString());
                    }
                }
            };
            debugDropDown.Items.Add(queueFromJsonItem);

            var throwExceptionItem = new Fluent.MenuItem {
                Header = "Throw exception"
            };
            throwExceptionItem.Click += (sender, args) =>
            {
                throw new InvalidOperationException("Rats.");
            };
            debugDropDown.Items.Add(throwExceptionItem);

            var addLogItem = new Fluent.MenuItem {
                Header = "Add 1 log item"
            };
            addLogItem.Click += (sender, args) =>
            {
                StaticResolver.Resolve <IAppLogger>().Log("This is a log item");
            };
            debugDropDown.Items.Add(addLogItem);

            var addTenLogItems = new Fluent.MenuItem {
                Header = "Add 10 log items"
            };
            addTenLogItems.Click += (sender, args) =>
            {
                for (int i = 0; i < 10; i++)
                {
                    StaticResolver.Resolve <IAppLogger>().Log("This is a log item");
                }
            };
            debugDropDown.Items.Add(addTenLogItems);

            var addLongLogItem = new Fluent.MenuItem {
                Header = "Add long log item"
            };
            addLongLogItem.Click += (sender, args) =>
            {
                StaticResolver.Resolve <IAppLogger>().Log("This is a log item\r\nthat is split into multiple lines\r\nOh yes indeed");
            };
            debugDropDown.Items.Add(addLongLogItem);

            var doAnActionItem = new Fluent.MenuItem {
                Header = "Perform action"
            };
            doAnActionItem.Click += (sender, args) =>
            {
                var app = (App)System.Windows.Application.Current;
                app.ChangeTheme(new Uri("/Themes/Dark.xaml", UriKind.Relative));
            };
            debugDropDown.Items.Add(doAnActionItem);

            this.toolsRibbonGroupBox.Items.Add(debugDropDown);
#endif

            this.DataContextChanged += this.OnDataContextChanged;
            TheDispatcher            = this.Dispatcher;

            this.statusText.Opacity = 0.0;

            NameScope.SetNameScope(this, new NameScope());
            this.RegisterName("StatusText", this.statusText);

            var storyboard = (Storyboard)this.FindResource("StatusTextStoryboard");
            storyboard.Completed += (sender, args) =>
            {
                this.statusText.Visibility = Visibility.Collapsed;
            };

            this.presetTreeViewContainer.PresetTreeView.OnHierarchyMouseUp += (sender, args) =>
            {
                this.presetButton.IsDropDownOpen = false;
            };

            this.presetButton.DropDownOpened += (sender, args) =>
            {
                var item = UIUtilities.FindDescendant <TreeViewItem>(this.presetTreeViewContainer.PresetTreeView, viewItem =>
                {
                    return(viewItem.Header == this.viewModel.PresetsService.SelectedPreset);
                });

                if (item != null)
                {
                    UIUtilities.BringIntoView(item);
                }
            };

            this.Loaded += (e, o) =>
            {
                this.RestoredWindowState = this.WindowState;
            };

            this.statusService.MessageShown += (o, e) =>
            {
                this.ShowStatusMessage(e.Value);
            };

            this.queueView.SelectionChanged += this.QueueView_SelectionChanged;
        }
示例#24
0
        public OptionsDialogViewModel(IUpdater updateService)
        {
            this.updater = updateService;

            this.Tabs = new List <string>
            {
                OptionsRes.GeneralTab,                                  // 0
                OptionsRes.FileNamingTab,                               // 1
                OptionsRes.ProcessTab,                                  // 2
                OptionsRes.AdvancedTab,                                 // 3
            };

            if (Utilities.SupportsUpdates)
            {
                this.Tabs.Add(OptionsRes.UpdatesTab);                 // 4
            }

            // UpdateStatus
            this.updater
            .WhenAnyValue(x => x.State)
            .Select(state =>
            {
                switch (state)
                {
                case UpdateState.NotStarted:
                    return(string.Empty);

                case UpdateState.DownloadingInfo:
                    return(OptionsRes.DownloadingInfoStatus);

                case UpdateState.DownloadingInstaller:
                    return(string.Format(OptionsRes.DownloadingStatus, this.updater.LatestVersion));

                case UpdateState.UpToDate:
                    return(OptionsRes.UpToDateStatus);

                case UpdateState.InstallerReady:
                    return(string.Format(OptionsRes.UpdateReadyStatus, this.updater.LatestVersion));

                case UpdateState.Failed:
                    return(OptionsRes.UpdateFailedStatus);

                default:
                    throw new ArgumentOutOfRangeException();
                }
            })
            .ToProperty(this, x => x.UpdateStatus, out this.updateStatus, scheduler: Scheduler.Immediate);

            // UpdateDownloading
            this.updater
            .WhenAnyValue(x => x.State)
            .Select(state => state == UpdateState.DownloadingInstaller)
            .ToProperty(this, x => x.UpdateDownloading, out this.updateDownloading);

            // UpdateProgressPercent
            this.updater
            .WhenAnyValue(x => x.UpdateDownloadProgressFraction)
            .Select(downloadFraction => downloadFraction * 100)
            .ToProperty(this, x => x.UpdateProgressPercent, out this.updateProgressPercent);

            // CpuThrottlingDisplay
            this.WhenAnyValue(x => x.CpuThrottlingCores, x => x.CpuThrottlingMaxCores, (cores, maxCores) =>
            {
                double currentFraction = (double)cores / maxCores;
                return(currentFraction.ToString("p0"));
            }).ToProperty(this, x => x.CpuThrottlingDisplay, out this.cpuThrottlingDisplay, deferSubscription: true, scheduler: Scheduler.Immediate);

            this.updatesEnabledConfig                 = Config.UpdatesEnabled;
            this.updatePromptTiming                   = CustomConfig.UpdatePromptTiming;
            this.defaultPath                          = Config.AutoNameOutputFolder;
            this.customFormat                         = Config.AutoNameCustomFormat;
            this.customFormatString                   = Config.AutoNameCustomFormatString;
            this.outputToSourceDirectory              = Config.OutputToSourceDirectory;
            this.preserveFolderStructureInBatch       = Config.PreserveFolderStructureInBatch;
            this.useCustomPreviewFolder               = Config.UseCustomPreviewFolder;
            this.previewOutputFolder                  = Config.PreviewOutputFolder;
            this.whenFileExists                       = CustomConfig.WhenFileExists;
            this.whenFileExistsBatch                  = CustomConfig.WhenFileExistsBatch;
            this.minimizeToTray                       = Config.MinimizeToTray;
            this.useCustomVideoPlayer                 = Config.UseCustomVideoPlayer;
            this.customVideoPlayer                    = Config.CustomVideoPlayer;
            this.useBuiltInPlayerForPreviews          = Config.UseBuiltInPlayerForPreviews;
            this.playSoundOnCompletion                = Config.PlaySoundOnCompletion;
            this.useCustomCompletionSound             = Config.UseCustomCompletionSound;
            this.customCompletionSound                = Config.CustomCompletionSound;
            this.workerProcessPriority                = Config.WorkerProcessPriority;
            this.logVerbosity                         = Config.LogVerbosity;
            this.copyLogToOutputFolder                = Config.CopyLogToOutputFolder;
            this.previewCount                         = Config.PreviewCount;
            this.rememberPreviousFiles                = Config.RememberPreviousFiles;
            this.showAudioTrackNameField              = Config.ShowAudioTrackNameField;
            this.enableLibDvdNav                      = Config.EnableLibDvdNav;
            this.deleteSourceFilesOnClearingCompleted = Config.DeleteSourceFilesOnClearingCompleted;
            this.preserveModifyTimeFiles              = Config.PreserveModifyTimeFiles;
            this.resumeEncodingOnRestart              = Config.ResumeEncodingOnRestart;
            this.useWorkerProcess                     = Config.UseWorkerProcess;
            this.minimumTitleLengthSeconds            = Config.MinimumTitleLengthSeconds;
            this.AutoPauseProcesses                   = new ObservableCollection <string>();
            this.videoFileExtensions                  = Config.VideoFileExtensions;
            this.cpuThrottlingCores                   = (int)Math.Round(this.CpuThrottlingMaxCores * Config.CpuThrottlingFraction);
            if (this.cpuThrottlingCores < 1)
            {
                this.cpuThrottlingCores = 1;
            }

            if (this.cpuThrottlingCores > this.CpuThrottlingMaxCores)
            {
                this.cpuThrottlingCores = this.CpuThrottlingMaxCores;
            }

            this.maxSimultaneousEncodes = Config.MaxSimultaneousEncodes;

            List <string> autoPauseList = CustomConfig.AutoPauseProcesses;

            if (autoPauseList != null)
            {
                foreach (string process in autoPauseList)
                {
                    this.AutoPauseProcesses.Add(process);
                }
            }

            // List of language codes and names: http://msdn.microsoft.com/en-us/goglobal/bb896001.aspx

            this.LanguageChoices =
                new List <InterfaceLanguage>
            {
                new InterfaceLanguage {
                    CultureCode = string.Empty, Display = OptionsRes.UseOSLanguage
                },
                new InterfaceLanguage {
                    CultureCode = "en-US", Display = "English"
                },
                new InterfaceLanguage {
                    CultureCode = "id-ID", Display = "Bahasa Indonesia / Indonesian"
                },
                new InterfaceLanguage {
                    CultureCode = "bs-Latn-BA", Display = "bosanski (Bosna i Hercegovina) / Bosnian (Latin)"
                },
                new InterfaceLanguage {
                    CultureCode = "cs-CZ", Display = "čeština / Czech"
                },
                new InterfaceLanguage {
                    CultureCode = "de-DE", Display = "Deutsch / German"
                },
                new InterfaceLanguage {
                    CultureCode = "es-ES", Display = "Español / Spanish"
                },
                new InterfaceLanguage {
                    CultureCode = "eu-ES", Display = "Euskara / Basque"
                },
                new InterfaceLanguage {
                    CultureCode = "fr-FR", Display = "Français / French"
                },
                new InterfaceLanguage {
                    CultureCode = "it-IT", Display = "italiano / Italian"
                },
                new InterfaceLanguage {
                    CultureCode = "hu-HU", Display = "Magyar / Hungarian"
                },
                new InterfaceLanguage {
                    CultureCode = "nl-BE", Display = "Nederlands / Dutch"
                },
                new InterfaceLanguage {
                    CultureCode = "pl-PL", Display = "polski / Polish"
                },
                new InterfaceLanguage {
                    CultureCode = "pt-PT", Display = "Português / Portuguese"
                },
                new InterfaceLanguage {
                    CultureCode = "pt-BR", Display = "Português (Brasil) / Portuguese (Brazil)"
                },
                new InterfaceLanguage {
                    CultureCode = "tr-TR", Display = "Türkçe / Turkish"
                },
                new InterfaceLanguage {
                    CultureCode = "ka-GE", Display = "ქართული / Georgian"
                },
                new InterfaceLanguage {
                    CultureCode = "ru-RU", Display = "русский / Russian"
                },
                new InterfaceLanguage {
                    CultureCode = "ko-KO", Display = "한국어 / Korean"
                },
                new InterfaceLanguage {
                    CultureCode = "zh-Hans", Display = "中文(简体) / Chinese (Simplified)"
                },
                new InterfaceLanguage {
                    CultureCode = "zh-Hant", Display = "中文(繁體) / Chinese (Traditional)"
                },
                new InterfaceLanguage {
                    CultureCode = "ja-JP", Display = "日本語 / Japanese"
                },
            };

            this.AppThemeChoices =
                new List <ComboChoice <AppThemeChoice> >
            {
                new ComboChoice <AppThemeChoice>(AppThemeChoice.Auto, EnumsRes.AppThemeChoice_Auto),
                new ComboChoice <AppThemeChoice>(AppThemeChoice.Light, EnumsRes.AppThemeChoice_Light),
                new ComboChoice <AppThemeChoice>(AppThemeChoice.Dark, EnumsRes.AppThemeChoice_Dark),
            };
            this.appTheme = this.AppThemeChoices.FirstOrDefault(t => t.Value == CustomConfig.AppTheme);
            if (this.appTheme == null)
            {
                this.appTheme = this.AppThemeChoices[0];
            }

            this.PriorityChoices = new List <ComboChoice>
            {
                new ComboChoice("High", OptionsRes.Priority_High),
                new ComboChoice("AboveNormal", OptionsRes.Priority_AboveNormal),
                new ComboChoice("Normal", OptionsRes.Priority_Normal),
                new ComboChoice("BelowNormal", OptionsRes.Priority_BelowNormal),
                new ComboChoice("Idle", OptionsRes.Priority_Idle),
            };

            this.interfaceLanguage = this.LanguageChoices.FirstOrDefault(l => l.CultureCode == Config.InterfaceLanguageCode);
            if (this.interfaceLanguage == null)
            {
                this.interfaceLanguage = this.LanguageChoices[0];
            }

            this.PlayerChoices = Players.All;
            if (this.PlayerChoices.Count > 0)
            {
                this.selectedPlayer = this.PlayerChoices[0];

                foreach (IVideoPlayer player in this.PlayerChoices)
                {
                    if (player.Id == Config.PreferredPlayer)
                    {
                        this.selectedPlayer = player;
                        break;
                    }
                }
            }

            if (!CommonUtilities.Beta)
            {
                Task.Run(async() =>
                {
                    this.betaInfo = await Updater.GetUpdateInfoAsync(beta: true);

                    this.betaInfoAvailable = false;
                    if (this.betaInfo != null)
                    {
                        if (this.betaInfo.LatestVersion.FillInWithZeroes() > Utilities.CurrentVersion)
                        {
                            this.betaInfoAvailable = true;
                        }

                        await DispatchUtilities.InvokeAsync(() =>
                        {
                            this.RaisePropertyChanged(nameof(this.BetaChangelogUrl));
                            this.RaisePropertyChanged(nameof(this.BetaSectionVisible));
                        });
                    }
                });
            }

            int tabIndex = Config.OptionsDialogLastTab;

            if (tabIndex >= this.Tabs.Count)
            {
                tabIndex = 0;
            }

            this.SelectedTabIndex = tabIndex;
        }
        public VideoFiltersPanelViewModel(EncodingWindowViewModel encodingWindowViewModel)
            : base(encodingWindowViewModel)
        {
            this.AutomaticChange = true;

            this.RegisterProfileProperties();

            this.DetelecineChoices = this.GetFilterPresetChoices(hb_filter_ids.HB_FILTER_DETELECINE);

            this.DeinterlaceChoices = new List <ComboChoice <VCDeinterlace> >
            {
                new ComboChoice <VCDeinterlace>(VCDeinterlace.Off, CommonRes.Off),
                new ComboChoice <VCDeinterlace>(VCDeinterlace.Yadif, EnumsRes.Deinterlace_Yadif),
                new ComboChoice <VCDeinterlace>(VCDeinterlace.Decomb, EnumsRes.Deinterlace_Decomb),
            };

            this.CombDetectChoices = this.GetFilterPresetChoices(hb_filter_ids.HB_FILTER_COMB_DETECT, "CombDetect_");

            this.DenoiseChoices = new List <ComboChoice <VCDenoise> >
            {
                new ComboChoice <VCDenoise>(VCDenoise.Off, CommonRes.Off),
                new ComboChoice <VCDenoise>(VCDenoise.hqdn3d, EnumsRes.Denoise_HQDN3D),
                new ComboChoice <VCDenoise>(VCDenoise.NLMeans, EnumsRes.Denoise_NLMeans),
            };

            this.DenoiseTuneChoices = this.GetFilterTuneChoices(hb_filter_ids.HB_FILTER_NLMEANS, "DenoiseTune_");



            // CustomDetelecineVisible
            this.WhenAnyValue(x => x.Detelecine, detelecine =>
            {
                return(detelecine == "custom");
            }).ToProperty(this, x => x.CustomDetelecineVisible, out this.customDetelecineVisible);

            // DeinterlacePresetChoices
            this.WhenAnyValue(x => x.DeinterlaceType)
            .Select(deinterlaceType =>
            {
                if (deinterlaceType == VCDeinterlace.Off)
                {
                    return(new List <ComboChoice>());
                }

                return(this.GetFilterPresetChoices(GetDeinterlaceFilter(deinterlaceType), "DeinterlacePreset_"));
            }).ToProperty(this, x => x.DeinterlacePresetChoices, out this.deinterlacePresetChoices);

            // DeinterlacePresetVisible
            this.WhenAnyValue(x => x.DeinterlaceType)
            .Select(deinterlaceType =>
            {
                return(deinterlaceType != VCDeinterlace.Off);
            }).ToProperty(this, x => x.DeinterlacePresetVisible, out this.deinterlacePresetVisible);

            // CustomDeinterlaceVisible
            this.WhenAnyValue(x => x.DeinterlaceType, x => x.DeinterlacePreset, (deinterlaceType, deinterlacePreset) =>
            {
                return(deinterlaceType != VCDeinterlace.Off && deinterlacePreset == "custom");
            }).ToProperty(this, x => x.CustomDeinterlaceVisible, out this.customDeinterlaceVisible);

            // CustomDeinterlaceToolTip
            this.WhenAnyValue(x => x.DeinterlaceType, deinterlaceType =>
            {
                if (deinterlaceType == VCDeinterlace.Off)
                {
                    return(string.Empty);
                }

                return(GetCustomFilterToolTip(GetDeinterlaceFilter(deinterlaceType)));
            }).ToProperty(this, x => x.CustomDeinterlaceToolTip, out this.customDeinterlaceToolTip);

            // CustomCombDetectVisible
            this.WhenAnyValue(x => x.CombDetect, combDetect =>
            {
                return(combDetect == "custom");
            }).ToProperty(this, x => x.CustomCombDetectVisible, out this.customCombDetectVisible);

            // DenoisePresetVisible
            this.WhenAnyValue(x => x.DenoiseType, denoise =>
            {
                return(denoise != VCDenoise.Off);
            }).ToProperty(this, x => x.DenoisePresetVisible, out this.denoisePresetVisible);

            // DenoisePresetChoices
            this.WhenAnyValue(x => x.DenoiseType)
            .Select(denoiseType =>
            {
                if (denoiseType == VCDenoise.Off)
                {
                    return(new List <ComboChoice>());
                }

                return(this.GetFilterPresetChoices(GetDenoiseFilter(denoiseType), "DenoisePreset_"));
            }).ToProperty(this, x => x.DenoisePresetChoices, out this.denoisePresetChoices);

            // DenoiseTuneVisible
            this.WhenAnyValue(x => x.DenoiseType, x => x.DenoisePreset, (denoiseType, denoisePreset) =>
            {
                return(denoiseType == VCDenoise.NLMeans && denoisePreset != "custom");
            }).ToProperty(this, x => x.DenoiseTuneVisible, out this.denoiseTuneVisible);

            // CustomDenoiseVisible
            this.WhenAnyValue(x => x.DenoiseType, x => x.DenoisePreset, (denoiseType, denoisePreset) =>
            {
                return(denoiseType != VCDenoise.Off && denoisePreset == "custom");
            }).ToProperty(this, x => x.CustomDenoiseVisible, out this.customDenoiseVisible);

            // CustomDenoiseToolTip
            this.WhenAnyValue(x => x.DenoiseType, denoiseType =>
            {
                if (denoiseType == VCDenoise.Off)
                {
                    return(string.Empty);
                }

                return(GetCustomFilterToolTip(GetDenoiseFilter(denoiseType)));
            }).ToProperty(this, x => x.CustomDenoiseToolTip, out this.customDenoiseToolTip);

            // DeblockText
            this.WhenAnyValue(x => x.Deblock, deblock =>
            {
                if (deblock >= MinDeblock)
                {
                    return(deblock.ToString(CultureInfo.CurrentCulture));
                }

                return(CommonRes.Off);
            }).ToProperty(this, x => x.DeblockText, out this.deblockText);

            // The deinterlace and denoise presets need another nudge to change after the lists have changed.
            this.WhenAnyValue(x => x.DeinterlaceType)
            .Subscribe(_ =>
            {
                DispatchUtilities.BeginInvoke(() =>
                {
                    this.RaisePropertyChanged(nameof(this.DeinterlacePreset));
                });
            });

            this.WhenAnyValue(x => x.DenoiseType)
            .Subscribe(_ =>
            {
                DispatchUtilities.BeginInvoke(() =>
                {
                    this.RaisePropertyChanged(nameof(this.DenoisePreset));
                });
            });

            this.AutomaticChange = false;
        }
示例#26
0
        private void ProcessPreviewImageWork(object state)
        {
            PreviewImageJob imageJob;
            bool            workLeft = true;

            while (workLeft)
            {
                lock (this.imageSync)
                {
                    if (this.previewImageWorkQueue.Count == 0)
                    {
                        this.previewImageQueueProcessing = false;
                        return;
                    }

                    imageJob = this.previewImageWorkQueue.Dequeue();
                    while (imageJob.UpdateVersion < updateVersion)
                    {
                        if (this.previewImageWorkQueue.Count == 0)
                        {
                            this.previewImageQueueProcessing = false;
                            return;
                        }

                        imageJob = this.previewImageWorkQueue.Dequeue();
                    }
                }

                string imagePath = Path.Combine(
                    Utilities.ImageCacheFolder,
                    Process.GetCurrentProcess().Id.ToString(CultureInfo.InvariantCulture),
                    imageJob.UpdateVersion.ToString(CultureInfo.InvariantCulture),
                    imageJob.PreviewIndex.ToString(CultureInfo.InvariantCulture) + ".bmp");
                BitmapSource imageSource = null;

                // Check the disc cache for the image
                lock (imageJob.ImageFileSync)
                {
                    if (File.Exists(imagePath))
                    {
                        Uri imageUri;
                        if (Uri.TryCreate(imagePath, UriKind.Absolute, out imageUri))
                        {
                            // When we read from disc cache the image is already transformed.
                            var bitmapImage = new BitmapImage();
                            bitmapImage.BeginInit();
                            bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
                            bitmapImage.UriSource   = imageUri;
                            bitmapImage.EndInit();
                            bitmapImage.Freeze();

                            imageSource = bitmapImage;
                        }
                        else
                        {
                            StaticResolver.Resolve <IAppLogger>().LogError($"Could not load cached preview image from {imagePath} . Did not parse as a URI.");
                        }
                    }
                }

                if (imageSource == null && !imageJob.ScanInstance.IsDisposed)
                {
                    // Make a HandBrake call to get the image
                    imageSource = BitmapUtilities.ConvertToBitmapImage(BitmapUtilities.ConvertByteArrayToBitmap(imageJob.ScanInstance.GetPreview(imageJob.Profile.CreatePreviewSettings(imageJob.Title), imageJob.PreviewIndex, imageJob.Profile.DeinterlaceType != VCDeinterlace.Off)));

                    // Transform the image as per rotation and reflection settings
                    VCProfile profile = imageJob.Profile;
                    if (profile.FlipHorizontal || profile.FlipVertical || profile.Rotation != VCPictureRotation.None)
                    {
                        imageSource = CreateTransformedBitmap(imageSource, profile);
                    }

                    // Start saving the image file in the background and continue to process the queue.
                    ThreadPool.QueueUserWorkItem(this.BackgroundFileSave, new SaveImageJob
                    {
                        PreviewNumber = imageJob.PreviewIndex,
                        UpdateVersion = imageJob.UpdateVersion,
                        FilePath      = imagePath,
                        Image         = imageSource,
                        ImageFileSync = imageJob.ImageFileSync
                    });
                }

                lock (this.imageSync)
                {
                    if (imageJob.UpdateVersion == updateVersion)
                    {
                        this.previewImageCache[imageJob.PreviewIndex] = imageSource;
                        int previewIndex = imageJob.PreviewIndex;
                        DispatchUtilities.BeginInvoke(() =>
                        {
                            this.ImageLoaded?.Invoke(this, new PreviewImageLoadInfo {
                                PreviewImage = imageSource, PreviewIndex = previewIndex
                            });
                            //this.previewBitmapSource = imageSource;
                            //this.RefreshFromBitmapImage();
                        });
                        //if (this.SelectedPreview == imageJob.PreviewIndex)
                        //   {
                        //    DispatchUtilities.BeginInvoke(() =>
                        //    {
                        //	    this.previewBitmapSource = imageSource;
                        //	    this.RefreshFromBitmapImage();
                        //    });
                        //   }
                    }

                    if (this.previewImageWorkQueue.Count == 0)
                    {
                        workLeft = false;
                        this.previewImageQueueProcessing = false;
                    }
                }
            }
        }
示例#27
0
 private void previewImageRefreshTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
 {
     this.waitingOnRefresh     = false;
     this.lastImageRefreshTime = DateTime.MinValue;
     DispatchUtilities.BeginInvoke(this.RefreshPreviews);
 }
示例#28
0
        private void GeneratePreviewImpl()
        {
            this.job = this.mainViewModel.EncodeJob;

            this.PreviewPercentComplete = 0;
            this.EncodeState            = PreviewEncodeState.EncodeStarting;
            this.cancelPending          = false;
            this.encodeCancelled        = false;

            this.SetPreviewFilePath();

            this.job.OutputPath = this.previewFilePath;

            if (this.job.Subtitles?.SourceSubtitles != null)
            {
                SourceSubtitle scanTrack = this.job.Subtitles.SourceSubtitles.FirstOrDefault(s => s.TrackNumber == 0);
                if (scanTrack != null)
                {
                    this.job.Subtitles.SourceSubtitles.Remove(scanTrack);
                }
            }

            this.encodeProxy = Utilities.CreateEncodeProxy();
            this.encodeProxy.EncodeStarted += (o, e) =>
            {
                DispatchUtilities.BeginInvoke(() =>
                {
                    this.EncodeState = PreviewEncodeState.Encoding;
                    if (this.cancelPending)
                    {
                        this.CancelPreviewImpl();
                    }
                });
            };
            this.encodeProxy.EncodeProgress += (o, e) =>
            {
                double totalWeight;
                double completeWeight;
                if (e.PassCount == 1)
                {
                    // Single pass, no subtitle scan
                    totalWeight    = 1;
                    completeWeight = e.FractionComplete;
                }
                else if (e.PassCount == 2 && e.PassId <= 0)
                {
                    // Single pass with subtitle scan
                    totalWeight = 1 + SubtitleScanCost;
                    if (e.PassId == -1)
                    {
                        // In subtitle scan
                        completeWeight = e.FractionComplete * SubtitleScanCost;
                    }
                    else
                    {
                        // In normal pass
                        completeWeight = SubtitleScanCost + e.FractionComplete;
                    }
                }
                else if (e.PassCount == 2 && e.PassId >= 1)
                {
                    // Two normal passes
                    totalWeight = 2;

                    if (e.PassId == 1)
                    {
                        // First pass
                        completeWeight = e.FractionComplete;
                    }
                    else
                    {
                        // Second pass
                        completeWeight = 1 + e.FractionComplete;
                    }
                }
                else
                {
                    // Two normal passes with subtitle scan
                    totalWeight = 2 + SubtitleScanCost;

                    if (e.PassId == -1)
                    {
                        // In subtitle scan
                        completeWeight = e.FractionComplete * SubtitleScanCost;
                    }
                    else if (e.PassId == 1)
                    {
                        // First normal pass
                        completeWeight = SubtitleScanCost + e.FractionComplete;
                    }
                    else
                    {
                        // Second normal pass
                        completeWeight = SubtitleScanCost + 1 + e.FractionComplete;
                    }
                }


                double fractionComplete = completeWeight / totalWeight;
                this.PreviewPercentComplete = fractionComplete * 100;
            };
            this.encodeProxy.EncodeCompleted += (o, e) =>
            {
                DispatchUtilities.BeginInvoke(() =>
                {
                    this.EncodeState = PreviewEncodeState.NotEncoding;

                    if (this.encodeCancelled)
                    {
                        this.logger.Log("Cancelled preview clip generation");
                    }
                    else
                    {
                        if (e.Error)
                        {
                            this.logger.Log(PreviewRes.PreviewClipGenerationFailedTitle);
                            Utilities.MessageBox.Show(PreviewRes.PreviewClipGenerationFailedMessage);
                        }
                        else
                        {
                            var previewFileInfo = new FileInfo(this.previewFilePath);
                            this.logger.Log("Finished preview clip generation. Size: " + Utilities.FormatFileSize(previewFileInfo.Length));

                            this.PlayPreview();
                        }
                    }
                });
            };

            this.logger.Log("Generating preview clip");
            this.logger.Log("  Path: " + this.job.OutputPath);
            this.logger.Log("  Title: " + this.job.Title);
            this.logger.Log("  Preview #: " + this.SelectedPreview);

            this.encodeProxy.StartEncode(this.job, this.logger, true, this.SelectedPreview, this.PreviewSeconds, this.job.Length.TotalSeconds);
        }
示例#29
0
        private void ProcessPreviewImageWork(object state)
        {
            PreviewImageJob imageJob;
            bool            workLeft = true;

            while (workLeft)
            {
                lock (this.imageSync)
                {
                    if (this.previewImageWorkQueue.Count == 0)
                    {
                        this.previewImageQueueProcessing = false;
                        return;
                    }

                    imageJob = this.previewImageWorkQueue.Dequeue();
                    while (imageJob.UpdateVersion < updateVersion)
                    {
                        if (this.previewImageWorkQueue.Count == 0)
                        {
                            this.previewImageQueueProcessing = false;
                            return;
                        }

                        imageJob = this.previewImageWorkQueue.Dequeue();
                    }
                }

                string       imagePath   = Path.Combine(Utilities.ImageCacheFolder, Process.GetCurrentProcess().Id.ToString(CultureInfo.InvariantCulture), imageJob.UpdateVersion.ToString(CultureInfo.InvariantCulture), imageJob.PreviewNumber + ".bmp");
                BitmapSource imageSource = null;

                // Check the disc cache for the image
                lock (imageJob.ImageFileSync)
                {
                    if (File.Exists(imagePath))
                    {
                        // When we read from disc cache the image is already transformed.
                        var bitmapImage = new BitmapImage();
                        bitmapImage.BeginInit();
                        bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
                        bitmapImage.UriSource   = new Uri(imagePath);
                        bitmapImage.EndInit();
                        bitmapImage.Freeze();

                        imageSource = bitmapImage;
                    }
                }

                if (imageSource == null && !imageJob.ScanInstance.IsDisposed)
                {
                    // Make a HandBrake call to get the image
                    imageSource = imageJob.ScanInstance.GetPreview(imageJob.Profile.CreatePreviewSettings(imageJob.Title), imageJob.PreviewNumber);

                    // Transform the image as per rotation and reflection settings
                    VCProfile profile = imageJob.Profile;
                    if (profile.FlipHorizontal || profile.FlipVertical || profile.Rotation != VCPictureRotation.None)
                    {
                        imageSource = CreateTransformedBitmap(imageSource, profile);
                    }

                    // Start saving the image file in the background and continue to process the queue.
                    ThreadPool.QueueUserWorkItem(this.BackgroundFileSave, new SaveImageJob
                    {
                        PreviewNumber = imageJob.PreviewNumber,
                        UpdateVersion = imageJob.UpdateVersion,
                        FilePath      = imagePath,
                        Image         = imageSource,
                        ImageFileSync = imageJob.ImageFileSync
                    });
                }

                lock (this.imageSync)
                {
                    if (imageJob.UpdateVersion == updateVersion)
                    {
                        this.previewImageCache[imageJob.PreviewNumber] = imageSource;
                        if (this.SelectedPreview == imageJob.PreviewNumber)
                        {
                            DispatchUtilities.BeginInvoke(() =>
                            {
                                this.previewBitmapSource = imageSource;
                                this.RefreshFromBitmapImage();
                            });
                        }
                    }

                    if (this.previewImageWorkQueue.Count == 0)
                    {
                        workLeft = false;
                        this.previewImageQueueProcessing = false;
                    }
                }
            }
        }