예제 #1
0
        public EncodeResultViewModel(EncodeResult result, EncodeJobViewModel job)
        {
            this.encodeResult = result;
            this.job          = job;

            Messenger.Default.Register <ScanningChangedMessage>(
                this,
                message =>
            {
                this.EditCommand.RaiseCanExecuteChanged();
            });
        }
예제 #2
0
		public EncodeResultViewModel(EncodeResult result, EncodeJobViewModel job)
		{
			this.encodeResult = result;
			this.job = job;

			Messenger.Default.Register<ScanningChangedMessage>(
				this,
				message =>
					{
						this.EditCommand.RaiseCanExecuteChanged();
					});
		}
예제 #3
0
        public void ScanNextJob()
        {
            EncodeJobViewModel jobVM = itemsToScan[currentJobIndex];

            var onDemandInstance = new HandBrakeInstance();

            onDemandInstance.Initialize(Config.LogVerbosity);
            onDemandInstance.ScanProgress += (o, e) =>
            {
                lock (this.currentJobIndexLock)
                {
                    this.currentJobProgress = e.Progress;
                    this.RaisePropertyChanged(() => this.Progress);
                }
            };
            onDemandInstance.ScanCompleted += (o, e) =>
            {
                jobVM.HandBrakeInstance = onDemandInstance;

                if (onDemandInstance.Titles.Count > 0)
                {
                    Title titleToEncode = Utilities.GetFeatureTitle(onDemandInstance.Titles, onDemandInstance.FeatureTitle);

                    jobVM.Job.Title        = titleToEncode.TitleNumber;
                    jobVM.Job.Length       = titleToEncode.Duration;
                    jobVM.Job.ChapterStart = 1;
                    jobVM.Job.ChapterEnd   = titleToEncode.Chapters.Count;
                }

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

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

            onDemandInstance.StartScan(jobVM.Job.SourcePath, Config.PreviewCount, 0);
        }
예제 #4
0
        public EncodeResultViewModel(EncodeResult result, EncodeJobViewModel job)
        {
            this.encodeResult = result;
            this.job          = job;

            this.Play = ReactiveCommand.Create();
            this.Play.Subscribe(_ => this.PlayImpl());

            this.OpenContainingFolder = ReactiveCommand.Create();
            this.OpenContainingFolder.Subscribe(_ => this.OpenContainingFolderImpl());

            this.Edit = ReactiveCommand.Create(this.WhenAnyValue(x => x.MainViewModel.VideoSourceState, videoSourceState =>
            {
                return(videoSourceState != VideoSourceState.Scanning);
            }));
            this.Edit.Subscribe(_ => this.EditImpl());

            this.OpenLog = ReactiveCommand.Create();
            this.OpenLog.Subscribe(_ => this.OpenLogImpl());

            this.CopyLog = ReactiveCommand.Create();
            this.CopyLog.Subscribe(_ => this.CopyLogImpl());
        }
예제 #5
0
 public EncodeResultViewModel(EncodeResult result, EncodeJobViewModel job)
 {
     this.encodeResult = result;
     this.job          = job;
 }
예제 #6
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();
		}
예제 #7
0
		/// <summary>
		/// Starts a scan of a video source
		/// </summary>
		/// <param name="path">The path to scan.</param>
		/// <param name="jobVM">The encode job choice to apply after the scan is finished.</param>
		private void StartScan(string path, EncodeJobViewModel jobVM = null)
		{
			this.ClearVideoSource();

			this.ScanProgress = 0;
			HandBrakeInstance oldInstance = this.scanInstance;

			this.logger.Log("Starting scan: " + path);

			this.scanInstance = new HandBrakeInstance();
			this.scanInstance.Initialize(Config.LogVerbosity);
			this.scanInstance.ScanProgress += (o, e) =>
			{
				this.ScanProgress = e.Progress * 100;
			};
			this.scanInstance.ScanCompleted += (o, e) =>
			{
				DispatchService.Invoke(() =>
				{
					this.ScanningSource = false;

					if (this.scanCancelledFlag)
					{
						this.SelectedSource = null;
						this.RaisePropertyChanged(() => this.SourcePicked);

						if (this.ScanCancelled != null)
						{
							this.ScanCancelled(this, new EventArgs());
						}

						this.logger.Log("Scan cancelled");

						if (this.pendingScan != null)
						{
							this.SetSource(this.pendingScan);

							this.pendingScan = null;
						}
					}
					else
					{
						this.SourceData = new VideoSource { Titles = this.scanInstance.Titles, FeatureTitle = this.scanInstance.FeatureTitle };

						// If scan failed source data will be null.
						if (this.sourceData != null)
						{
							if (jobVM != null)
							{
								this.ApplyEncodeJobChoices(jobVM);
							}

							if (jobVM == null && this.SelectedSource != null &&
							    (this.SelectedSource.Type == SourceType.File || this.SelectedSource.Type == SourceType.VideoFolder))
							{
								SourceHistory.AddToHistory(this.SourcePath);
							}
						}

						this.logger.Log("Scan completed");
					}

					this.logger.Log("");
				});
			};

			this.ScanError = false;
			this.ScanningSource = true;
			this.scanCancelledFlag = false;
			this.scanInstance.StartScan(path, Config.PreviewCount, TimeSpan.FromSeconds(Config.MinimumTitleLengthSeconds));

			if (oldInstance != null)
			{
				this.ProcessingVM.CleanupHandBrakeInstanceIfUnused(oldInstance);
			}
		}
예제 #8
0
		// Brings up specified job for editing, doing a scan if necessary.
		public void EditJob(EncodeJobViewModel jobVM, bool isQueueItem = true)
		{
			VCJob job = jobVM.Job;

			if (this.PresetsVM.SelectedPreset.IsModified)
			{
				MessageBoxResult dialogResult = Utilities.MessageBox.Show(this, MainRes.SaveChangesPresetMessage, MainRes.SaveChangesPresetTitle, MessageBoxButton.YesNoCancel);
				if (dialogResult == MessageBoxResult.Yes)
				{
					this.PresetsVM.SavePreset();
				}
				else if (dialogResult == MessageBoxResult.No)
				{
					this.PresetsVM.RevertPreset(userInitiated: false);
				}
				else if (dialogResult == MessageBoxResult.Cancel)
				{
					return;
				}
			}

			if (jobVM.HandBrakeInstance != null && jobVM.HandBrakeInstance == this.ScanInstance)
			{
				this.ApplyEncodeJobChoices(jobVM);
				Messenger.Default.Send(new RefreshPreviewMessage());
			}
			else if (jobVM.VideoSource != null)
			{
				// Set current scan to cached scan
				this.scanInstance = jobVM.HandBrakeInstance;
				this.SourceData = jobVM.VideoSource;
				this.LoadVideoSourceMetadata(job, jobVM.VideoSourceMetadata);

				this.ApplyEncodeJobChoices(jobVM);
			}
			else
			{
				string jobPath = job.SourcePath;
				string jobRoot = Path.GetPathRoot(jobPath);

				// We need to reconstruct the source metadata since the program has shut down since the job
				// was created.
				var videoSourceMetadata = new VideoSourceMetadata();

				switch (job.SourceType)
				{
					case SourceType.Dvd:
						DriveInformation driveInfo = this.DriveCollection.FirstOrDefault(d => string.Compare(d.RootDirectory, jobRoot, StringComparison.OrdinalIgnoreCase) == 0);
						if (driveInfo == null)
						{
							Ioc.Container.GetInstance<IMessageBoxService>().Show(MainRes.DiscNotInDriveError);
							return;
						}

						videoSourceMetadata.Name = driveInfo.VolumeLabel;
						videoSourceMetadata.DriveInfo = driveInfo;
						break;
					case SourceType.File:
						videoSourceMetadata.Name = Utilities.GetSourceNameFile(job.SourcePath);
						break;
					case SourceType.VideoFolder:
						videoSourceMetadata.Name = Utilities.GetSourceNameFolder(job.SourcePath);
						break;
				}

				this.LoadVideoSourceMetadata(job, videoSourceMetadata);
				this.StartScan(job.SourcePath, jobVM);
			}

			string presetName = isQueueItem ? MainRes.PresetNameRestoredFromQueue : MainRes.PresetNameRestoredFromCompleted;

			var queuePreset = new PresetViewModel(
				new Preset
				{
					IsBuiltIn = false,
					IsModified = false,
					IsQueue = true,
					Name = presetName,
					EncodingProfile = jobVM.Job.EncodingProfile.Clone()
				});

			this.PresetsVM.InsertQueuePreset(queuePreset);

			if (isQueueItem)
			{
				// Since it's been sent back for editing, remove the queue item
				this.ProcessingVM.EncodeQueue.Remove(jobVM);
			}

			this.PresetsVM.SaveUserPresets();
		}
예제 #9
0
		public EncodeJobViewModel CreateEncodeJobVM()
		{
			var newEncodeJobVM = new EncodeJobViewModel(this.EncodeJob);
			newEncodeJobVM.HandBrakeInstance = this.scanInstance;
			newEncodeJobVM.VideoSource = this.SourceData;
			newEncodeJobVM.VideoSourceMetadata = this.GetVideoSourceMetadata();
			newEncodeJobVM.SourceParentFolder = this.OutputPathVM.SourceParentFolder;
			newEncodeJobVM.ManualOutputPath = this.OutputPathVM.ManualOutputPath;
			newEncodeJobVM.NameFormatOverride = this.OutputPathVM.NameFormatOverride;
			newEncodeJobVM.PresetName = this.PresetsVM.SelectedPreset.DisplayName;

			return newEncodeJobVM;
		}