/// <summary> /// Starts an encode, given a VidCoder job and some extra data. /// </summary> /// <param name="job">The VidCoder job to run.</param> /// <param name="previewNumber">The preview number to run.</param> /// <param name="previewSeconds">The number of seconds the preview should be.</param> /// <param name="defaultChapterNameFormat">The default format for chapter names.</param> public void StartEncode( VCJob job, int previewNumber, int previewSeconds, string defaultChapterNameFormat) { this.StartEncodeInternal( job.SourcePath, job.Title, scanObject => { SourceTitle encodeTitle = scanObject.TitleList.FirstOrDefault(title => title.Index == job.Title); if (encodeTitle != null) { JsonEncodeFactory factory = new JsonEncodeFactory(ServiceLocator.Current.GetInstance <ILogger>()); JsonEncodeObject encodeObject = factory.CreateJsonObject( job, encodeTitle, defaultChapterNameFormat, previewNumber, previewSeconds, this.passedPreviewCount); return(JsonConvert.SerializeObject(encodeObject, JsonSettings.HandBrakeJsonSerializerSettings)); } else { return(null); } }); }
public void Refresh() { if (this.mainViewModel.SelectedTitle != null) { var profile = this.presetsService.SelectedPreset.Preset.EncodingProfile; OutputSizeInfo outputSizeInfo = JsonEncodeFactory.GetOutputSize(profile, this.mainViewModel.SelectedTitle); if (this.Size == null || !outputSizeInfo.Equals(this.Size)) { this.Size = outputSizeInfo; } } else { this.Size = null; } }
public Task StartEncodeAsync( VCJob job, IAppLogger logger, bool preview, int previewNumber, int previewSeconds, double overallSelectedLengthSeconds) { this.logger = logger; this.StartEncodeInternal( job.SourcePath, job.Title, scanObject => { SourceTitle encodeTitle = scanObject.TitleList.FirstOrDefault(title => title.Index == job.Title); if (encodeTitle != null) { JsonEncodeFactory factory = new JsonEncodeFactory(logger); JsonEncodeObject jsonEncodeObject = factory.CreateJsonObject( job, encodeTitle, EncodingRes.DefaultChapterName, preview ? previewNumber : -1, previewSeconds, Config.PreviewCount); return(JsonConvert.SerializeObject(jsonEncodeObject, JsonSettings.HandBrakeJsonSerializerSettings)); } else { return(null); } }); return(Task.CompletedTask); }
public static PreviewSettings CreatePreviewSettings(this VCProfile profile, SourceTitle title) { VCCropping cropping = JsonEncodeFactory.GetCropping(profile, title); // HB doesn't expect us to give it a 0 width and height so we need to guard against that int sanitizedWidth = profile.Width > 0 ? profile.Width : title.Geometry.Width - cropping.Left - cropping.Right; int sanitizedHeight = profile.Height > 0 ? profile.Height : title.Geometry.Height - cropping.Top - cropping.Bottom; return(new PreviewSettings { Anamorphic = EnumConverter.Convert <VCAnamorphic, Anamorphic>(profile.Anamorphic), Cropping = JsonEncodeFactory.GetCropping(profile, title).GetHbCropping(), Width = sanitizedWidth, Height = sanitizedHeight, MaxWidth = profile.MaxWidth, MaxHeight = profile.MaxHeight, KeepDisplayAspect = profile.KeepDisplayAspect, Modulus = profile.Modulus, PixelAspectX = 1, PixelAspectY = 1, TitleNumber = title.Index }); }
public static PreviewSettings CreatePreviewSettings(this VCProfile profile, SourceTitle title) { VCCropping cropping = JsonEncodeFactory.GetCropping(profile, title); var outputSize = JsonEncodeFactory.GetOutputSize(profile, title); int width = outputSize.ScaleWidth; int height = outputSize.ScaleHeight; return(new PreviewSettings { Anamorphic = EnumConverter.Convert <VCAnamorphic, Anamorphic>(profile.Anamorphic), Cropping = cropping.GetHbCropping(), Width = width, Height = height, MaxWidth = width, MaxHeight = height, KeepDisplayAspect = true, Modulus = profile.Modulus, PixelAspectX = 1, PixelAspectY = 1, TitleNumber = title.Index }); }
public SizingPanelViewModel(EncodingWindowViewModel encodingWindowViewModel) : base(encodingWindowViewModel) { this.AutomaticChange = true; this.RotationChoices = new List <RotationViewModel> { new RotationViewModel { Rotation = VCPictureRotation.None, Display = CommonRes.None, Image = "/Icons/Empty.png", ShowImage = false }, new RotationViewModel { Rotation = VCPictureRotation.Clockwise90, Display = EncodingRes.Rotation_Clockwise90, Image = "/Icons/rotate_90_cw.png" }, new RotationViewModel { Rotation = VCPictureRotation.Clockwise270, Display = EncodingRes.Rotation_Counterclockwise90, Image = "/Icons/rotate_90_ccw.png" }, new RotationViewModel { Rotation = VCPictureRotation.Clockwise180, Display = EncodingRes.Rotation_180, Image = "/Icons/rotate_180.png" } }; this.SizingModeChoices = new List <ComboChoice <VCSizingMode> > { new ComboChoice <VCSizingMode>(VCSizingMode.Automatic, CommonRes.Automatic), new ComboChoice <VCSizingMode>(VCSizingMode.Manual, EncodingRes.SizingModeManual), }; this.ScalingModeChoices = new List <ComboChoice <VCScalingMode> > { new ComboChoice <VCScalingMode>(VCScalingMode.DownscaleOnly, EncodingRes.ScalingMode_DownscaleOnly), new ComboChoice <VCScalingMode>(VCScalingMode.UpscaleFill, EncodingRes.ScalingMode_Fill), new ComboChoice <VCScalingMode>(VCScalingMode.Upscale2X, string.Format(EncodingRes.UpscaleMaxFormat, 2)), new ComboChoice <VCScalingMode>(VCScalingMode.Upscale3X, string.Format(EncodingRes.UpscaleMaxFormat, 3)), new ComboChoice <VCScalingMode>(VCScalingMode.Upscale4X, string.Format(EncodingRes.UpscaleMaxFormat, 4)), }; this.PaddingModeChoices = new List <ComboChoice <VCPaddingMode> > { new ComboChoice <VCPaddingMode>(VCPaddingMode.None, CommonRes.None), new ComboChoice <VCPaddingMode>(VCPaddingMode.Fill, EncodingRes.PaddingMode_Fill), new ComboChoice <VCPaddingMode>(VCPaddingMode.Width, EncodingRes.PaddingMode_Width), new ComboChoice <VCPaddingMode>(VCPaddingMode.Height, EncodingRes.PaddingMode_Height), new ComboChoice <VCPaddingMode>(VCPaddingMode.Custom, CommonRes.Custom), }; this.RegisterProfileProperties(); // WidthLabel this.WhenAnyValue(x => x.SizingMode, x => x.PaddingMode, x => x.ScalingMode, (sizingMode, paddingMode, scalingMode) => { if (sizingMode == VCSizingMode.Manual) { return(EncodingRes.WidthLabel); } switch (paddingMode) { case VCPaddingMode.Fill: case VCPaddingMode.Width: return(EncodingRes.WidthLabel); case VCPaddingMode.Height: return(EncodingRes.MaxWidthLabel); case VCPaddingMode.None: case VCPaddingMode.Custom: switch (scalingMode) { case VCScalingMode.UpscaleFill: return(EncodingRes.TargetWidthLabel); default: return(EncodingRes.MaxWidthLabel); } } return(string.Empty); }).ToProperty(this, x => x.WidthLabel, out this.widthLabel); // HeightLabel this.WhenAnyValue(x => x.SizingMode, x => x.PaddingMode, x => x.ScalingMode, (sizingMode, paddingMode, scalingMode) => { if (sizingMode == VCSizingMode.Manual) { return(EncodingRes.HeightLabel); } switch (paddingMode) { case VCPaddingMode.Fill: case VCPaddingMode.Height: return(EncodingRes.HeightLabel); case VCPaddingMode.Width: return(EncodingRes.MaxHeightLabel); case VCPaddingMode.None: case VCPaddingMode.Custom: switch (scalingMode) { case VCScalingMode.UpscaleFill: return(EncodingRes.TargetHeightLabel); default: return(EncodingRes.MaxHeightLabel); } } return(string.Empty); }).ToProperty(this, x => x.HeightLabel, out this.heightLabel); // AllowEmptyResolution this.WhenAnyValue(x => x.SizingMode, x => x.PaddingMode, x => x.ScalingMode, (sizingMode, paddingMode, scalingMode) => { if (sizingMode == VCSizingMode.Manual) { return(false); } switch (paddingMode) { case VCPaddingMode.None: case VCPaddingMode.Custom: return(scalingMode != VCScalingMode.UpscaleFill);; default: return(false); } }).ToProperty(this, x => x.AllowEmptyResolution, out this.allowEmptyResolution); // InputPreview this.MainViewModel.WhenAnyValue(x => x.SelectedTitle).Select(selectedTitle => { var previewLines = new List <SizingPreviewLineViewModel>(); if (selectedTitle == null) { return(previewLines); } string inputStorageResolutionString = selectedTitle.Geometry.Width + " x " + selectedTitle.Geometry.Height; if (selectedTitle.Geometry.PAR.Num == selectedTitle.Geometry.PAR.Den) { previewLines.Add(new SizingPreviewLineViewModel(EncodingRes.ResolutionLabel, inputStorageResolutionString)); } else { previewLines.Add(new SizingPreviewLineViewModel(EncodingRes.StorageResolutionLabel, inputStorageResolutionString)); previewLines.Add(new SizingPreviewLineViewModel(EncodingRes.PixelAspectRatioLabel, CreateParDisplayString(selectedTitle.Geometry.PAR.Num, selectedTitle.Geometry.PAR.Den))); double pixelAspectRatio = ((double)selectedTitle.Geometry.PAR.Num) / selectedTitle.Geometry.PAR.Den; double displayWidth = selectedTitle.Geometry.Width * pixelAspectRatio; int displayWidthRounded = (int)Math.Round(displayWidth); string displayResolutionString = displayWidthRounded + " x " + selectedTitle.Geometry.Height; previewLines.Add(new SizingPreviewLineViewModel(EncodingRes.DisplayResolutionLabel, displayResolutionString)); } return(previewLines); }).ToProperty(this, x => x.InputPreview, out this.inputPreview); // OutputPreview this.outputSizeService.WhenAnyValue(x => x.Size).Select(size => { var previewLines = new List <SizingPreviewLineViewModel>(); if (size == null) { return(previewLines); } string outputStorageResolutionString = size.OutputWidth + " x " + size.OutputHeight; if (size.Par.Num == size.Par.Den) { previewLines.Add(new SizingPreviewLineViewModel(EncodingRes.ResolutionLabel, outputStorageResolutionString)); } else { previewLines.Add(new SizingPreviewLineViewModel(EncodingRes.StorageResolutionLabel, outputStorageResolutionString)); previewLines.Add(new SizingPreviewLineViewModel(EncodingRes.PixelAspectRatioLabel, CreateParDisplayString(size.Par.Num, size.Par.Den))); string displayResolutionString = Math.Round(size.OutputWidth * (((double)size.Par.Num) / size.Par.Den)) + " x " + size.OutputHeight; previewLines.Add(new SizingPreviewLineViewModel(EncodingRes.DisplayResolutionLabel, displayResolutionString)); } return(previewLines); }).ToProperty(this, x => x.OutputPreview, out this.outputPreview); // PadColorEnabled this.WhenAnyValue(x => x.PaddingMode, paddingMode => { return(paddingMode != VCPaddingMode.None); }).ToProperty(this, x => x.PadColorEnabled, out this.padColorEnabled); // CroppingUIEnabled this.WhenAnyValue(x => x.CroppingType, croppingType => { return(croppingType == VCCroppingType.Custom); }).ToProperty(this, x => x.CroppingUIEnabled, out this.croppingUIEnabled); // Update the underlying profile when our local Crop properties change. This only applies for // CroppingType.Custom this.WhenAnyValue(x => x.CropTop) .Skip(1) .Subscribe(cropTop => { this.UpdateProfileProperty( () => this.Profile.Cropping, nameof(this.Profile.Cropping.Top), nameof(this.CropTop), cropTop, raisePropertyChanged: false); }); this.WhenAnyValue(x => x.CropBottom) .Skip(1) .Subscribe(cropBottom => { this.UpdateProfileProperty( () => this.Profile.Cropping, nameof(this.Profile.Cropping.Bottom), nameof(this.CropBottom), cropBottom, raisePropertyChanged: false); }); this.WhenAnyValue(x => x.CropLeft) .Skip(1) .Subscribe(cropLeft => { this.UpdateProfileProperty( () => this.Profile.Cropping, nameof(this.Profile.Cropping.Left), nameof(this.CropLeft), cropLeft, raisePropertyChanged: false); }); this.WhenAnyValue(x => x.CropRight) .Skip(1) .Subscribe(cropRight => { this.UpdateProfileProperty( () => this.Profile.Cropping, nameof(this.Profile.Cropping.Right), nameof(this.CropRight), cropRight, raisePropertyChanged: false); }); // Auto-fill the cropping properties when type is Auto or None this.WhenAnyValue( x => x.CroppingType, x => x.MainViewModel.SelectedTitle, (croppingType, selectedTitle) => { return(new { croppingType, selectedTitle }); }) .Subscribe(x => { bool oldAutoValue = this.AutomaticChange; if (x.croppingType == VCCroppingType.None) { this.AutomaticChange = true; this.CropTop = 0; this.CropBottom = 0; this.CropLeft = 0; this.CropRight = 0; } else if (x.croppingType == VCCroppingType.Automatic) { this.AutomaticChange = true; if (x.selectedTitle == null) { this.CropTop = 0; this.CropBottom = 0; this.CropLeft = 0; this.CropRight = 0; } else { this.CropTop = x.selectedTitle.Crop[0]; this.CropBottom = x.selectedTitle.Crop[1]; this.CropLeft = x.selectedTitle.Crop[2]; this.CropRight = x.selectedTitle.Crop[3]; } } this.AutomaticChange = oldAutoValue; }); // When the preset changes, update the local crop values for Custom. this.PresetsService.WhenAnyValue(x => x.SelectedPreset.Preset.EncodingProfile) .Subscribe(_ => { if (this.PresetsService.SelectedPreset.Preset.EncodingProfile.CroppingType == VCCroppingType.Custom) { bool oldAutoValue = this.AutomaticChange; this.AutomaticChange = true; var cropping = this.PresetsService.SelectedPreset.Preset.EncodingProfile.Cropping; this.CropLeft = cropping.Left; this.CropTop = cropping.Top; this.CropRight = cropping.Right; this.CropBottom = cropping.Bottom; this.AutomaticChange = oldAutoValue; } }); // PaddingUIEnabled this.WhenAnyValue(x => x.SizingMode, x => x.PaddingMode, (sizingMode, paddingMode) => { if (sizingMode == VCSizingMode.Manual) { return(true); } return(paddingMode == VCPaddingMode.Custom); }).ToProperty(this, x => x.PaddingUIEnabled, out this.paddingUIEnabled); // Update the underlying profile when our local Pad properties change. this.WhenAnyValue(x => x.PadTop) .Skip(1) .Subscribe(padTop => { this.UpdateProfileProperty( () => this.Profile.Padding, nameof(this.Profile.Padding.Top), nameof(this.PadTop), padTop, raisePropertyChanged: false); }); this.WhenAnyValue(x => x.PadBottom) .Skip(1) .Subscribe(padBottom => { this.UpdateProfileProperty( () => this.Profile.Padding, nameof(this.Profile.Padding.Bottom), nameof(this.PadBottom), padBottom, raisePropertyChanged: false); }); this.WhenAnyValue(x => x.PadLeft) .Skip(1) .Subscribe(padLeft => { this.UpdateProfileProperty( () => this.Profile.Padding, nameof(this.Profile.Padding.Left), nameof(this.PadLeft), padLeft, raisePropertyChanged: false); }); this.WhenAnyValue(x => x.PadRight) .Skip(1) .Subscribe(padRight => { this.UpdateProfileProperty( () => this.Profile.Padding, nameof(this.Profile.Padding.Right), nameof(this.PadRight), padRight, raisePropertyChanged: false); }); // Auto-fill the padding properties when UI is disabled this.WhenAnyValue( x => x.SizingMode, x => x.ScalingMode, x => x.PaddingMode, x => x.Width, x => x.Height, x => x.MainViewModel.SelectedTitle, (sizingMode, scalingMode, paddingMode, width, height, selectedTitle) => { return(new { sizingMode, scalingMode, paddingMode, width, height, selectedTitle }); }) .Subscribe(x => { bool oldAutoValue = this.AutomaticChange; if (x.sizingMode == VCSizingMode.Automatic && x.paddingMode == VCPaddingMode.None) { this.AutomaticChange = true; this.PadTop = 0; this.PadBottom = 0; this.PadLeft = 0; this.PadRight = 0; } else if (x.sizingMode == VCSizingMode.Automatic && x.paddingMode != VCPaddingMode.Custom) { if (x.selectedTitle == null) { this.PadTop = 0; this.PadBottom = 0; this.PadLeft = 0; this.PadRight = 0; } else { // Calculate the correct padding from input variables OutputSizeInfo outputSize = JsonEncodeFactory.GetOutputSize(this.Profile, x.selectedTitle); this.PadTop = outputSize.Padding.Top; this.PadBottom = outputSize.Padding.Bottom; this.PadLeft = outputSize.Padding.Left; this.PadRight = outputSize.Padding.Right; } } this.AutomaticChange = oldAutoValue; }); // When the preset changes, update the local pad values. this.PresetsService.WhenAnyValue(x => x.SelectedPreset.Preset.EncodingProfile) .Subscribe(_ => { VCProfile profile = this.PresetsService.SelectedPreset.Preset.EncodingProfile; if (profile.SizingMode == VCSizingMode.Manual || profile.PaddingMode == VCPaddingMode.Custom) { bool oldAutoValue = this.AutomaticChange; this.AutomaticChange = true; var padding = profile.Padding; this.PadLeft = padding.Left; this.PadTop = padding.Top; this.PadRight = padding.Right; this.PadBottom = padding.Bottom; this.AutomaticChange = oldAutoValue; } }); this.AutomaticChange = false; }