/// <summary>
        /// Gets the total number of seconds on the given encode job.
        /// </summary>
        /// <param name="job">The encode job to query.</param>
        /// <param name="title">The title being encoded.</param>
        /// <returns>The total number of seconds of video to encode.</returns>
        internal static double GetJobLengthSeconds(EncodeJob job, Title title)
        {
            switch (job.RangeType)
            {
                case VideoRangeType.All:
                    return title.Duration.TotalSeconds;
                case VideoRangeType.Chapters:
                    TimeSpan duration = TimeSpan.Zero;
                    for (int i = job.ChapterStart; i <= job.ChapterEnd; i++)
                    {
                        duration += title.Chapters[i - 1].Duration;
                    }

                    return duration.TotalSeconds;
                case VideoRangeType.Seconds:
                    return job.SecondsEnd - job.SecondsStart;
                case VideoRangeType.Frames:
                    return (job.FramesEnd - job.FramesStart) / title.Framerate;
            }

            return 0;
        }
Esempio n. 2
0
		public TitleSelectionViewModel(Title title, QueueTitlesDialogViewModel titlesDialogVM)
		{
			this.Title = title;
			this.titlesDialogVM = titlesDialogVM;
		}
        /// <summary>
        /// Gets the size in bytes for the audio with the given parameters.
        /// </summary>
        /// <param name="job">The encode job.</param>
        /// <param name="lengthSeconds">The length of the encode in seconds.</param>
        /// <param name="title">The title to encode.</param>
        /// <param name="outputTrackList">The list of tracks to encode.</param>
        /// <returns>The size in bytes for the audio with the given parameters.</returns>
        internal static long GetAudioSize(EncodeJob job, double lengthSeconds, Title title, List<Tuple<AudioEncoding, int>> outputTrackList)
        {
            long audioBytes = 0;

            foreach (Tuple<AudioEncoding, int> outputTrack in outputTrackList)
            {
                AudioEncoding encoding = outputTrack.Item1;
                AudioTrack track = title.AudioTracks[outputTrack.Item2 - 1];

                int samplesPerFrame = HandBrakeUtils.GetAudioSamplesPerFrame(encoding.Encoder);
                int audioBitrate;

                HBAudioEncoder audioEncoder = Encoders.GetAudioEncoder(encoding.Encoder);

                if (audioEncoder.IsPassthrough)
                {
                    // Input bitrate is in bits/second.
                    audioBitrate = track.Bitrate / 8;
                }
                else if (encoding.EncodeRateType == AudioEncodeRateType.Quality)
                {
                    // Can't predict size of quality targeted audio encoding.
                    audioBitrate = 0;
                }
                else
                {
                    int outputBitrate;
                    if (encoding.Bitrate > 0)
                    {
                        outputBitrate = encoding.Bitrate;
                    }
                    else
                    {
                        outputBitrate = Encoders.GetDefaultBitrate(
                            audioEncoder,
                            encoding.SampleRateRaw == 0 ? track.SampleRate : encoding.SampleRateRaw,
                            Encoders.SanitizeMixdown(Encoders.GetMixdown(encoding.Mixdown), audioEncoder, track.ChannelLayout));
                    }

                    // Output bitrate is in kbps.
                    audioBitrate = outputBitrate * 1000 / 8;
                }

                audioBytes += (long)(lengthSeconds * audioBitrate);

                // Audio overhead
                audioBytes += encoding.SampleRateRaw * ContainerOverheadPerFrame / samplesPerFrame;
            }

            return audioBytes;
        }
Esempio n. 4
0
        /// <summary>
        /// Gets a list of encodings and target track indices (1-based).
        /// </summary>
        /// <param name="job">The encode job</param>
        /// <param name="title">The title the job is meant to encode.</param>
        /// <returns>A list of encodings and target track indices (1-based).</returns>
        private List<Tuple<AudioEncoding, int>> GetOutputTracks(EncodeJob job, Title title)
        {
            var list = new List<Tuple<AudioEncoding, int>>();

            foreach (AudioEncoding encoding in job.EncodingProfile.AudioEncodings)
            {
                if (encoding.InputNumber == 0)
                {
                    // Add this encoding for all chosen tracks
                    foreach (int chosenTrack in job.ChosenAudioTracks)
                    {
                        // In normal cases we'll never have a chosen audio track that doesn't exist but when batch encoding
                        // we just choose the first audio track without checking if it exists.
                        if (chosenTrack <= title.AudioTracks.Count)
                        {
                            list.Add(new Tuple<AudioEncoding, int>(encoding, chosenTrack));
                        }
                    }
                }
                else if (encoding.InputNumber <= job.ChosenAudioTracks.Count)
                {
                    // Add this encoding for the specified track, if it exists
                    int trackNumber = job.ChosenAudioTracks[encoding.InputNumber - 1];

                    // In normal cases we'll never have a chosen audio track that doesn't exist but when batch encoding
                    // we just choose the first audio track without checking if it exists.
                    if (trackNumber <= title.AudioTracks.Count)
                    {
                        list.Add(new Tuple<AudioEncoding, int>(encoding, trackNumber));
                    }
                }
            }

            return list;
        }
Esempio n. 5
0
        /// <summary>
        /// Calculates the output size for a non-anamorphic job.
        /// </summary>
        /// <param name="profile">The encoding profile for the job.</param>
        /// <param name="title">The title being encoded.</param>
        /// <returns>The dimensions of the final encode.</returns>
        private static Size CalculateNonAnamorphicOutput(EncodingProfile profile, Title title)
        {
            int sourceWidth = title.Resolution.Width;
            int sourceHeight = title.Resolution.Height;

            int width = profile.Width;
            int height = profile.Height;

            Cropping crop;
            if (profile.CustomCropping)
            {
                crop = profile.Cropping;
            }
            else
            {
                crop = title.AutoCropDimensions;
            }

            sourceWidth -= crop.Left;
            sourceWidth -= crop.Right;

            sourceHeight -= crop.Top;
            sourceHeight -= crop.Bottom;

            double croppedAspectRatio = ((double)sourceWidth * title.ParVal.Width) / (sourceHeight * title.ParVal.Height);

            if (width == 0)
            {
                width = sourceWidth;
            }

            if (profile.MaxWidth > 0 && width > profile.MaxWidth)
            {
                width = profile.MaxWidth;
            }

            if (height == 0)
            {
                height = sourceHeight;
            }

            if (profile.MaxHeight > 0 && height > profile.MaxHeight)
            {
                height = profile.MaxHeight;
            }

            if (profile.KeepDisplayAspect)
            {
                if ((profile.Width == 0 && profile.Height == 0) || profile.Width == 0)
                {
                    width = (int)((double)height * croppedAspectRatio);
                    if (profile.MaxWidth > 0 && width > profile.MaxWidth)
                    {
                        width = profile.MaxWidth;
                        height = (int)((double)width / croppedAspectRatio);
                        height = GetNearestValue(height, PictureAutoSizeModulus);
                    }

                    width = GetNearestValue(width, PictureAutoSizeModulus);
                }
                else if (profile.Height == 0)
                {
                    height = (int)((double)width / croppedAspectRatio);
                    if (profile.MaxHeight > 0 && height > profile.MaxHeight)
                    {
                        height = profile.MaxHeight;
                        width = (int)((double)height * croppedAspectRatio);
                        width = GetNearestValue(width, PictureAutoSizeModulus);
                    }

                    height = GetNearestValue(height, PictureAutoSizeModulus);
                }
            }

            return new Size(width, height);
        }
Esempio n. 6
0
		public void SetChosenTracks(List<int> chosenAudioTracks, Title selectedTitle)
		{
			DispatchService.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.AudioTracks[chosenAudioTracks[i] - 1].NoTrackDisplay;
					}

					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(() => this.TargetStreamIndex);

				this.targetStreamIndex = previousIndex;
				this.RaisePropertyChanged(() => this.TargetStreamIndex);
			});
		}
Esempio n. 7
0
        /// <summary>
        /// Converts a native title to a Title object.
        /// </summary>
        /// <param name="title">The native title structure.</param>
        /// <returns>The managed Title object.</returns>
        private Title ConvertTitle(hb_title_s title)
        {
            var newTitle = new Title
            {
                TitleNumber = title.index,
                Resolution = new Size(title.width, title.height),
                ParVal = new Size(title.pixel_aspect_width, title.pixel_aspect_height),
                Duration = TimeSpan.FromSeconds(title.duration / 90000),
                AutoCropDimensions = new Cropping
                {
                    Top = title.crop[0],
                    Bottom = title.crop[1],
                    Left = title.crop[2],
                    Right = title.crop[3]
                },
                AspectRatio = title.aspect,
                AngleCount = title.angle_count,
                VideoCodecName = title.video_codec_name,
                Framerate = ((double)title.rate) / title.rate_base
            };

            switch (title.type)
            {
                case hb_title_type_anon.HB_STREAM_TYPE:
                    newTitle.InputType = InputType.Stream;
                    break;
                case hb_title_type_anon.HB_DVD_TYPE:
                    newTitle.InputType = InputType.Dvd;
                    break;
                case hb_title_type_anon.HB_BD_TYPE:
                    newTitle.InputType = InputType.Bluray;
                    break;
            }

            int currentSubtitleTrack = 1;
            List<hb_subtitle_s> subtitleList = InteropUtilities.ConvertList<hb_subtitle_s>(title.list_subtitle);
            foreach (hb_subtitle_s subtitle in subtitleList)
            {
                var newSubtitle = new Subtitle
                {
                    TrackNumber = currentSubtitleTrack,
                    Language = subtitle.lang,
                    LanguageCode = subtitle.iso639_2
                };

                if (subtitle.format == hb_subtitle_s_subtype.PICTURESUB)
                {
                    newSubtitle.SubtitleType = SubtitleType.Picture;
                }
                else if (subtitle.format == hb_subtitle_s_subtype.TEXTSUB)
                {
                    newSubtitle.SubtitleType = SubtitleType.Text;
                }

                switch (subtitle.source)
                {
                    case hb_subtitle_s_subsource.CC608SUB:
                        newSubtitle.SubtitleSource = SubtitleSource.CC608;
                        break;
                    case hb_subtitle_s_subsource.CC708SUB:
                        newSubtitle.SubtitleSource = SubtitleSource.CC708;
                        break;
                    case hb_subtitle_s_subsource.SRTSUB:
                        newSubtitle.SubtitleSource = SubtitleSource.SRT;
                        break;
                    case hb_subtitle_s_subsource.SSASUB:
                        newSubtitle.SubtitleSource = SubtitleSource.SSA;
                        break;
                    case hb_subtitle_s_subsource.TX3GSUB:
                        newSubtitle.SubtitleSource = SubtitleSource.TX3G;
                        break;
                    case hb_subtitle_s_subsource.UTF8SUB:
                        newSubtitle.SubtitleSource = SubtitleSource.UTF8;
                        break;
                    case hb_subtitle_s_subsource.VOBSUB:
                        newSubtitle.SubtitleSource = SubtitleSource.VobSub;
                        break;
                    default:
                        break;
                }

                newTitle.Subtitles.Add(newSubtitle);

                currentSubtitleTrack++;
            }

            int currentAudioTrack = 1;
            List<hb_audio_s> audioList = InteropUtilities.ConvertList<hb_audio_s>(title.list_audio);
            foreach (hb_audio_s audio in audioList)
            {
                var newAudio = new AudioTrack
                {
                    TrackNumber = currentAudioTrack,
                    Codec = Converters.NativeToAudioCodec(audio.config.input.codec),
                    CodecId = audio.config.input.codec,
                    Language = audio.config.lang.simple,
                    LanguageCode = audio.config.lang.iso639_2,
                    Description = audio.config.lang.description,
                    ChannelLayout = audio.config.input.channel_layout,
                    SampleRate = audio.config.input.samplerate,
                    Bitrate = audio.config.input.bitrate
                };

                newTitle.AudioTracks.Add(newAudio);

                currentAudioTrack++;
            }

            List<hb_chapter_s> chapterList = InteropUtilities.ConvertList<hb_chapter_s>(title.list_chapter);
            foreach (hb_chapter_s chapter in chapterList)
            {
                var newChapter = new Chapter
                {
                    ChapterNumber = chapter.index,
                    Duration = TimeSpan.FromSeconds(((double)chapter.duration) / 90000)
                };

                newTitle.Chapters.Add(newChapter);
            }

            return newTitle;
        }
        /// <summary>
        /// Gets the size in bytes for the audio with the given parameters.
        /// </summary>
        /// <param name="job">The encode job.</param>
        /// <param name="lengthSeconds">The length of the encode in seconds.</param>
        /// <param name="title">The title to encode.</param>
        /// <param name="outputTrackList">The list of tracks to encode.</param>
        /// <returns>The size in bytes for the audio with the given parameters.</returns>
        internal static long GetAudioSize(EncodeJob job, double lengthSeconds, Title title, List<Tuple<AudioEncoding, int>> outputTrackList)
        {
            long audioBytes = 0;

            foreach (Tuple<AudioEncoding, int> outputTrack in outputTrackList)
            {
                AudioEncoding encoding = outputTrack.Item1;
                AudioTrack track = title.AudioTracks[outputTrack.Item2 - 1];

                int samplesPerFrame = HandBrakeUtils.GetAudioSamplesPerFrame(encoding.Encoder);
                int audioBitrate;

                if (Utilities.IsPassthrough(encoding.Encoder))
                {
                    // Input bitrate is in bits/second.
                    audioBitrate = track.Bitrate / 8;
                }
                else
                {
                    // Output bitrate is in kbps.
                    audioBitrate = encoding.Bitrate * 1000 / 8;
                }

                audioBytes += (long)(lengthSeconds * audioBitrate);

                // Audio overhead
                audioBytes += encoding.SampleRateRaw * ContainerOverheadPerFrame / samplesPerFrame;
            }

            return audioBytes;
        }
Esempio n. 9
0
		public AudioEncodingViewModel(AudioEncoding audioEncoding, Title selectedTitle, List<int> chosenAudioTracks, string containerName, AudioPanelViewModel audioPanelVM)
		{
			this.initializing = true;
			this.audioPanelVM = audioPanelVM;

			this.targetStreams = new ObservableCollection<TargetStreamViewModel>();
			this.targetStreamIndex = audioEncoding.InputNumber;

			this.SetChosenTracks(chosenAudioTracks, selectedTitle);

			this.audioEncoders = new List<AudioEncoderViewModel>();
			this.mixdownChoices = new List<MixdownViewModel>();

			this.containerName = containerName;
			this.RefreshEncoderChoices();

			HBAudioEncoder hbAudioEncoder = Encoders.GetAudioEncoder(audioEncoding.Encoder);
			if (hbAudioEncoder.IsPassthrough)
			{
				this.selectedAudioEncoder = this.audioEncoders[0];
				this.selectedPassthrough = audioEncoding.Encoder;
			}
			else
			{
				this.selectedAudioEncoder = this.audioEncoders.Skip(1).FirstOrDefault(e => e.Encoder.ShortName == audioEncoding.Encoder);
				this.selectedPassthrough = "copy";
			}

			if (this.selectedAudioEncoder == null)
			{
				this.selectedAudioEncoder = this.audioEncoders[1];
			}

			this.RefreshMixdownChoices();
			this.RefreshBitrateChoices();
			this.RefreshSampleRateChoices();

			this.SelectMixdown(Encoders.GetMixdown(audioEncoding.Mixdown));

			this.sampleRate = audioEncoding.SampleRateRaw;

			if (!this.HBAudioEncoder.SupportsQuality)
			{
				this.encodeRateType = AudioEncodeRateType.Bitrate;
			}
			else
			{
				this.encodeRateType = audioEncoding.EncodeRateType;
			}

			this.audioQuality = audioEncoding.Quality;

			if (audioEncoding.Compression >= 0)
			{
				this.audioCompression = audioEncoding.Compression;
			}
			else
			{
				this.audioCompression = this.HBAudioEncoder.DefaultCompression;
			}

			this.selectedBitrate = this.BitrateChoices.SingleOrDefault(b => b.Bitrate == audioEncoding.Bitrate);
			if (this.selectedBitrate == null)
			{
				this.selectedBitrate = this.BitrateChoices.First();
			}

			this.gain = audioEncoding.Gain;
			this.drc = audioEncoding.Drc;
			this.passthroughIfPossible = audioEncoding.PassthroughIfPossible;
			this.name = audioEncoding.Name;

			Messenger.Default.Register<SelectedTitleChangedMessage>(
				this,
				message =>
					{
						this.RefreshMixdownChoices();
						this.RefreshBitrateChoices();
						this.RefreshDrc();
					});

			Messenger.Default.Register<AudioInputChangedMessage>(
				this,
				message =>
					{
						this.RefreshMixdownChoices();
						this.RefreshBitrateChoices();
						this.RefreshDrc();
					});

			Messenger.Default.Register<OptionsChangedMessage>(
				this,
				message =>
					{
						this.RaisePropertyChanged(() => this.NameVisible);
					});

			Messenger.Default.Register<ContainerChangedMessage>(
				this,
				message =>
					{
						this.containerName = message.ContainerName;
						this.RefreshEncoderChoices();
					});

			this.initializing = false;
		}
Esempio n. 10
0
 /// <summary>
 /// Gets the cropping to use for the given encoding profile and title.
 /// </summary>
 /// <param name="profile">The encoding profile to use.</param>
 /// <param name="title">The title being encoded.</param>
 /// <returns>The cropping to use for the encode.</returns>
 private static Cropping GetCropping(EncodingProfile profile, Title title)
 {
     Cropping crop;
     switch (profile.CroppingType)
     {
         case CroppingType.Automatic:
             crop = title.AutoCropDimensions;
             break;
         case CroppingType.Custom:
             crop = profile.Cropping;
             break;
         default:
             crop = new Cropping();
             break;
     }
     return crop;
 }
Esempio n. 11
0
 /// <summary>
 /// Gets the 1-based title index of the given title.
 /// </summary>
 /// <param name="title">The title to look up</param>
 /// <returns>The 1-based title index of the given title.</returns>
 private int GetTitleIndex(Title title)
 {
     return this.Titles.IndexOf(title) + 1;
 }
Esempio n. 12
0
		// Applies the encode job choices to the viewmodel. Part of editing a queued item,
		// assumes a scan has been done first with the data available.
		private void ApplyEncodeJobChoices(EncodeJobViewModel jobVM)
		{
			if (this.sourceData == null || this.sourceData.Titles.Count == 0)
			{
				return;
			}

			VCJob job = jobVM.Job;

			// Title
			Title newTitle = this.sourceData.Titles.FirstOrDefault(t => t.TitleNumber == job.Title);
			if (newTitle == null)
			{
				newTitle = this.sourceData.Titles[0];
			}

			this.selectedTitle = newTitle;

			// Angle
			this.PopulateAnglesList();

			if (job.Angle <= this.selectedTitle.AngleCount)
			{
				this.angle = job.Angle;
			}
			else
			{
				this.angle = 0;
			}

			// Range
			this.PopulateChapterSelectLists();
			this.rangeType = job.RangeType;
			if (this.rangeType == VideoRangeType.All)
			{
				if (this.selectedTitle.Chapters.Count > 1)
				{
					this.rangeType = VideoRangeType.Chapters;
				}
				else
				{
					this.rangeType = VideoRangeType.Seconds;
				}
			}

			switch (this.rangeType)
			{
				case VideoRangeType.Chapters:
					if (job.ChapterStart > this.selectedTitle.Chapters.Count ||
						job.ChapterEnd > this.selectedTitle.Chapters.Count ||
						job.ChapterStart == 0 ||
						job.ChapterEnd == 0)
					{
						this.selectedStartChapter = this.StartChapters.FirstOrDefault(c => c.Chapter == this.selectedTitle.Chapters[0]);
						this.selectedEndChapter = this.EndChapters.FirstOrDefault(c => c.Chapter == this.selectedTitle.Chapters[this.selectedTitle.Chapters.Count - 1]);
					}
					else
					{
						this.selectedStartChapter = this.StartChapters.FirstOrDefault(c => c.Chapter == this.selectedTitle.Chapters[job.ChapterStart - 1]);
						this.selectedEndChapter = this.EndChapters.FirstOrDefault(c => c.Chapter == this.selectedTitle.Chapters[job.ChapterEnd - 1]);
					}

					break;
				case VideoRangeType.Seconds:
					if (this.selectedTitle.Duration == TimeSpan.Zero)
					{
						throw new InvalidOperationException("Title's duration is 0, cannot continue.");
					}

					if (job.SecondsStart < this.selectedTitle.Duration.TotalSeconds + 1 &&
						job.SecondsEnd < this.selectedTitle.Duration.TotalSeconds + 1)
					{
						TimeSpan startTime = TimeSpan.FromSeconds(job.SecondsStart);
						TimeSpan endTime = TimeSpan.FromSeconds(job.SecondsEnd);

						if (endTime > this.selectedTitle.Duration)
						{
							endTime = this.selectedTitle.Duration;
						}

						if (startTime > endTime - Constants.TimeRangeBuffer)
						{
							startTime = endTime - Constants.TimeRangeBuffer;
						}

						if (startTime < TimeSpan.Zero)
						{
							startTime = TimeSpan.Zero;
						}

						this.SetRangeTimeStart(startTime);
						this.SetRangeTimeEnd(endTime);
					}
					else
					{
						this.SetRangeTimeStart(TimeSpan.Zero);
						this.SetRangeTimeEnd(this.selectedTitle.Duration);
					}

					// We saw a problem with a job getting seconds 0-0 after a queue edit, add some sanity checking.
					if (this.TimeRangeEnd == TimeSpan.Zero)
					{
						this.SetRangeTimeEnd(this.selectedTitle.Duration);
					}

					break;
				case VideoRangeType.Frames:
					if (job.FramesStart < this.selectedTitle.Frames + 1 &&
						job.FramesEnd < this.selectedTitle.Frames + 1)
					{
						this.framesRangeStart = job.FramesStart;
						this.framesRangeEnd = job.FramesEnd;
					}
					else
					{
						this.framesRangeStart = 0;
						this.framesRangeEnd = this.selectedTitle.Frames;
					}

					break;
				default:
					throw new ArgumentOutOfRangeException();
			}

			// Audio tracks
			this.AudioChoices.Clear();
			foreach (int chosenTrack in job.ChosenAudioTracks)
			{
				if (chosenTrack <= this.selectedTitle.AudioTracks.Count)
				{
					this.AudioChoices.Add(new AudioChoiceViewModel { SelectedIndex = chosenTrack - 1 });
				}
			}

			// Subtitles (standard+SRT)
			this.CurrentSubtitles.SourceSubtitles = new List<SourceSubtitle>();
			this.CurrentSubtitles.SrtSubtitles = new List<SrtSubtitle>();
			if (job.Subtitles.SourceSubtitles != null)
			{
				foreach (SourceSubtitle sourceSubtitle in job.Subtitles.SourceSubtitles)
				{
					if (sourceSubtitle.TrackNumber <= this.selectedTitle.Subtitles.Count)
					{
						this.CurrentSubtitles.SourceSubtitles.Add(sourceSubtitle);
					}
				}
			}

			if (job.Subtitles.SrtSubtitles != null)
			{
				foreach (SrtSubtitle srtSubtitle in job.Subtitles.SrtSubtitles)
				{
					this.CurrentSubtitles.SrtSubtitles.Add(srtSubtitle);
				}
			}

			// Custom chapter markers
			this.UseDefaultChapterNames = job.UseDefaultChapterNames;

			if (job.UseDefaultChapterNames)
			{
				this.CustomChapterNames = null;
			}
			else
			{
				if (this.CustomChapterNames != null && this.selectedTitle.Chapters.Count == this.CustomChapterNames.Count)
				{
					this.CustomChapterNames = job.CustomChapterNames;
				}
			}

			// Output path
			this.OutputPathVM.OutputPath = job.OutputPath;
			this.OutputPathVM.SourceParentFolder = jobVM.SourceParentFolder;
			this.OutputPathVM.ManualOutputPath = jobVM.ManualOutputPath;
			this.OutputPathVM.NameFormatOverride = jobVM.NameFormatOverride;

			// Encode profile handled above this in EditJob

			this.RaisePropertyChanged(() => this.SourceIcon);
			this.RaisePropertyChanged(() => this.SourceText);
			this.RaisePropertyChanged(() => this.SelectedTitle);
			this.RaisePropertyChanged(() => this.SelectedStartChapter);
			this.RaisePropertyChanged(() => this.SelectedEndChapter);
			this.RaisePropertyChanged(() => this.StartChapters);
			this.RaisePropertyChanged(() => this.EndChapters);
			this.RaisePropertyChanged(() => this.TimeRangeStart);
			this.RaisePropertyChanged(() => this.TimeRangeStartBar);
			this.RaisePropertyChanged(() => this.TimeRangeEnd);
			this.RaisePropertyChanged(() => this.TimeRangeEndBar);
			this.RaisePropertyChanged(() => this.FramesRangeStart);
			this.RaisePropertyChanged(() => this.FramesRangeEnd);
			this.RaisePropertyChanged(() => this.RangeType);
			this.RaisePropertyChanged(() => this.UsingChaptersRange);
			this.RaisePropertyChanged(() => this.RangeBarVisible);
			this.RaisePropertyChanged(() => this.SecondsRangeVisible);
			this.RaisePropertyChanged(() => this.FramesRangeVisible);
			this.RaisePropertyChanged(() => this.SubtitlesSummary);
			this.RaisePropertyChanged(() => this.ChapterMarkersSummary);
			this.RaisePropertyChanged(() => this.ShowChapterMarkerUI);
			this.RaisePropertyChanged(() => this.Angle);
			this.RaisePropertyChanged(() => this.Angles);

			this.RefreshRangePreview();
		}
Esempio n. 13
0
		// Automatically pick the correct subtitles on the given job.
		// Only relies on input from settings and the current title.
		private void AutoPickSubtitles(VCJob job, Title title, bool useCurrentContext = false)
		{
			job.Subtitles = new Subtitles { SourceSubtitles = new List<SourceSubtitle>(), SrtSubtitles = new List<SrtSubtitle>() };
			switch (CustomConfig.AutoSubtitle)
			{
				case AutoSubtitleType.Disabled:
					// Only pick subtitles when we have previous context.
					if (useCurrentContext)
					{
						foreach (SourceSubtitle sourceSubtitle in this.main.CurrentSubtitles.SourceSubtitles)
						{
							if (sourceSubtitle.TrackNumber == 0)
							{
								job.Subtitles.SourceSubtitles.Add(sourceSubtitle.Clone());
							}
							else if (
								title.Subtitles.Count > sourceSubtitle.TrackNumber - 1 &&
								this.main.SelectedTitle.Subtitles[sourceSubtitle.TrackNumber - 1].LanguageCode == title.Subtitles[sourceSubtitle.TrackNumber - 1].LanguageCode)
							{
								job.Subtitles.SourceSubtitles.Add(sourceSubtitle.Clone());
							}
						}
					}
					break;
				case AutoSubtitleType.ForeignAudioSearch:
					job.Subtitles.SourceSubtitles.Add(
						new SourceSubtitle
						{
							TrackNumber = 0,
							BurnedIn = Config.AutoSubtitleBurnIn,
							Forced = true,
							Default = true
						});
					break;
				case AutoSubtitleType.Language:
					string languageCode = Config.SubtitleLanguageCode;
					bool audioSame = false;
					bool burnIn = Config.AutoSubtitleLanguageBurnIn;
					if (job.ChosenAudioTracks.Count > 0 && title.AudioTracks.Count > 0)
					{
						if (title.AudioTracks[job.ChosenAudioTracks[0] - 1].LanguageCode == languageCode)
						{
							audioSame = true;
						}
					}

					if (!Config.AutoSubtitleOnlyIfDifferent || !audioSame)
					{
						List<Subtitle> nativeSubtitles = title.Subtitles.Where(subtitle => subtitle.LanguageCode == languageCode).ToList();
						if (nativeSubtitles.Count > 0)
						{
							if (Config.AutoSubtitleAll)
							{
								foreach (Subtitle subtitle in nativeSubtitles)
								{
									job.Subtitles.SourceSubtitles.Add(new SourceSubtitle
									{
										BurnedIn = false,
										Default = false,
										Forced = false,
										TrackNumber = subtitle.TrackNumber
									});
								}
							}
							else
							{
								job.Subtitles.SourceSubtitles.Add(new SourceSubtitle
								{
									BurnedIn = burnIn,
									Default = false,
									Forced = false,
									TrackNumber = nativeSubtitles[0].TrackNumber
								});
							}
						}
					}

					break;
				case AutoSubtitleType.All:
					foreach (Subtitle subtitle in title.Subtitles)
					{
						job.Subtitles.SourceSubtitles.Add(
							new SourceSubtitle
							{
								TrackNumber = subtitle.TrackNumber,
								BurnedIn = false,
								Default = false,
								Forced = false
							});
					}
					break;
				default:
					throw new ArgumentOutOfRangeException();
			}
		}
Esempio n. 14
0
		// Automatically pick the correct audio on the given job.
		// Only relies on input from settings and the current title.
		private void AutoPickAudio(VCJob job, Title title, bool useCurrentContext = false)
		{
			job.ChosenAudioTracks = new List<int>();
			switch (CustomConfig.AutoAudio)
			{
				case AutoAudioType.Disabled:
					if (title.AudioTracks.Count > 0)
					{
						if (useCurrentContext)
						{
							// With previous context, pick similarly
							foreach (AudioChoiceViewModel audioVM in this.main.AudioChoices)
							{
								int audioIndex = audioVM.SelectedIndex;

								if (title.AudioTracks.Count > audioIndex && this.main.SelectedTitle.AudioTracks[audioIndex].LanguageCode == title.AudioTracks[audioIndex].LanguageCode)
								{
									job.ChosenAudioTracks.Add(audioIndex + 1);
								}
							}

							// If we didn't manage to match any existing audio tracks, use the first audio track.
							if (this.main.AudioChoices.Count > 0 && job.ChosenAudioTracks.Count == 0)
							{
								job.ChosenAudioTracks.Add(1);
							}
						}
						else
						{
							// With no previous context, just pick the first track
							job.ChosenAudioTracks.Add(1);
						}
					}

					break;
				case AutoAudioType.Language:
					List<AudioTrack> nativeTracks = title.AudioTracks.Where(track => track.LanguageCode == Config.AudioLanguageCode).ToList();
					if (nativeTracks.Count > 0)
					{
						if (Config.AutoAudioAll)
						{
							foreach (AudioTrack audioTrack in nativeTracks)
							{
								job.ChosenAudioTracks.Add(audioTrack.TrackNumber);
							}
						}
						else
						{
							job.ChosenAudioTracks.Add(nativeTracks[0].TrackNumber);
						}
					}
					break;
				case AutoAudioType.All:
					foreach (AudioTrack audioTrack in title.AudioTracks)
					{
						job.ChosenAudioTracks.Add(audioTrack.TrackNumber);
					}
					break;
				default:
					throw new ArgumentOutOfRangeException();
			}

			// If none get chosen, pick the first one.
			if (job.ChosenAudioTracks.Count == 0 && title.AudioTracks.Count > 0)
			{
				job.ChosenAudioTracks.Add(1);
			}
		}