예제 #1
0
        /// <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);
                }
            });
        }
예제 #2
0
        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;
            }
        }
예제 #3
0
        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);
        }
예제 #4
0
        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
            });
        }
예제 #5
0
        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
            });
        }
예제 #6
0
        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;
        }