public static QueueTask GenerateFullQuery(frmMain mainWindow) { // Create the CLI Query string query = string.Empty; query += SourceQuery(mainWindow, mainWindow.drop_mode.SelectedIndex, 0, null); query += DestinationQuery(mainWindow, QueryEncodeMode.Standard); query += GenerateTabbedComponentsQuery(mainWindow, true, QueryPictureSettingsMode.UserInterfaceSettings, 0, 0); // Create the Queue Task and setup the EncodeTask model object. Preset preset = mainWindow.treeView_presets.SelectedNode.Tag as Preset; bool isCustom = true; if (preset != null && preset.IsBuildIn) { isCustom = false; } EncodeTask task = CreateEncodeTaskObject(mainWindow); QueueTask queueTask = new QueueTask(query) { Source = task.Source, Destination = task.Destination, Title = mainWindow.GetTitle(), CustomQuery = (mainWindow.rtf_query.Text != string.Empty) || isCustom, Task = task, Query = query, }; return queueTask; }
/// <summary> /// The get encode job. /// </summary> /// <param name="task"> /// The task. /// </param> /// <returns> /// The <see cref="EncodeJob"/>. /// </returns> public static EncodeJob GetEncodeJob(QueueTask task) { // Sanity Checking if (task == null || task.Task == null) { return null; } return GetEncodeJob(task.Task); }
/// <summary> /// Add the CLI Query to the Log File. /// </summary> /// <param name="encJob"> /// The Encode Job Object /// </param> /// <returns> /// The create cli log header. /// </returns> public static StringBuilder CreateCliLogHeader(QueueTask encJob) { StringBuilder logHeader = new StringBuilder(); logHeader.AppendLine(String.Format("{0}", Init.HandBrakeGuiVersionString)); logHeader.AppendLine(String.Format("OS: {0}", Environment.OSVersion)); logHeader.AppendLine(String.Format("CPU: {0}", SystemInfo.GetCpuCount)); logHeader.Append(String.Format("Ram: {0} MB, ", SystemInfo.TotalPhysicalMemory)); logHeader.AppendLine(String.Format("Screen: {0}x{1}", SystemInfo.ScreenBounds.Bounds.Width, SystemInfo.ScreenBounds.Bounds.Height)); logHeader.AppendLine(String.Format("Temp Dir: {0}", Path.GetTempPath())); logHeader.AppendLine(String.Format("Install Dir: {0}", Application.StartupPath)); logHeader.AppendLine(String.Format("Data Dir: {0}\n", Application.UserAppDataPath)); if (encJob != null) { logHeader.AppendLine(String.Format("CLI Query: {0}", encJob.Query)); logHeader.AppendLine(String.Format("User Query: {0}", encJob.CustomQuery)); } logHeader.AppendLine("-------------------------------------------"); return logHeader; }
/// <summary> /// Start an Encode /// </summary> public void StartEncode() { if (this.queueProcessor.IsProcessing) { this.errorService.ShowMessageBox("HandBrake is already encoding.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } // Check if we already have jobs, and if we do, just start the queue. if (this.queueProcessor.QueueManager.Count != 0) { this.queueProcessor.Start(); return; } // Otherwise, perform Santiy Checking then add to the queue and start if everything is ok. if (this.ScannedSource == null || this.CurrentTask == null) { this.errorService.ShowMessageBox("You must first scan a source.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } if (string.IsNullOrEmpty(this.Destination)) { this.errorService.ShowMessageBox("The Destination field was empty.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } if (File.Exists(this.Destination)) { MessageBoxResult result = this.errorService.ShowMessageBox("The current file already exists, do you wish to overwrite it?", "Question", MessageBoxButton.YesNo, MessageBoxImage.Question); if (result == MessageBoxResult.No) { return; } } // Create the Queue Task and Start Processing QueueTask task = new QueueTask { Task = new EncodeTask(this.CurrentTask), CustomQuery = false }; this.queueProcessor.QueueManager.Add(task); this.queueProcessor.Start(); this.IsEncoding = true; }
/// <summary> /// Start with a LibHb EncodeJob Object /// </summary> /// <param name="job"> /// The job. /// </param> /// <param name="enableLogging"> /// The enable Logging. /// </param> public void Start(QueueTask job, bool enableLogging) { this.startTime = DateTime.Now; this.loggingEnabled = enableLogging; try { // Sanity Checking and Setup if (this.IsEncoding) { throw new Exception("HandBrake is already encoding."); } this.IsEncoding = true; // Get an EncodeJob object for the Interop Library EncodeJob encodeJob = InteropModelCreator.GetEncodeJob(job); // Enable logging if required. if (enableLogging) { try { this.SetupLogging(job); } catch (Exception) { this.IsEncoding = false; throw; } } // Prvent the system from sleeping if the user asks if (this.userSettingService.GetUserSetting<bool>(ASUserSettingConstants.PreventSleep) ) { Win32.PreventSleep(); } // Verify the Destination Path Exists, and if not, create it. this.VerifyEncodeDestinationPath(job); // Start the Encode this.instance.StartEncode(encodeJob); // Set the Process Priority switch (this.userSettingService.GetUserSetting<string>(ASUserSettingConstants.ProcessPriority)) { case "Realtime": Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.RealTime; break; case "High": Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High; break; case "Above Normal": Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.AboveNormal; break; case "Normal": Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.Normal; break; case "Low": Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.Idle; break; default: Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.BelowNormal; break; } // Fire the Encode Started Event this.InvokeEncodeStarted(EventArgs.Empty); } catch (Exception exc) { this.InvokeEncodeCompleted(new EncodeCompletedEventArgs(false, exc, "An Error has occured.")); } }
/// <summary> /// Update the UI after the scan has completed /// </summary> /// <param name="sender"> /// The sender. /// </param> /// <param name="e"> /// The e. /// </param> private void SourceScanScanCompleted(object sender, EventArgs e) { if (this.InvokeRequired) { this.BeginInvoke(new ScanCompletedStatus(this.SourceScanScanCompleted), new[] { sender, e }); return; } try { currentSource = SourceScan.SouceData; // Setup some GUI components drp_dvdtitle.Items.Clear(); if (currentSource.Titles.Count != 0) drp_dvdtitle.Items.AddRange(currentSource.Titles.ToArray()); foreach (Title title in currentSource.Titles) { if (title.MainTitle) { drp_dvdtitle.SelectedItem = title; } } if (drp_dvdtitle.SelectedItem == null && drp_dvdtitle.Items.Count > 0) { drp_dvdtitle.SelectedIndex = 0; } // Enable the creation of chapter markers if the file is an image of a dvd if (drop_chapterStart.Items.Count > 0) { int start, end; int.TryParse(drop_chapterStart.Items[0].ToString(), out start); int.TryParse(drop_chapterFinish.Items[drop_chapterFinish.Items.Count - 1].ToString(), out end); if (end > start) Check_ChapterMarkers.Enabled = true; else { Check_ChapterMarkers.Enabled = false; Check_ChapterMarkers.Checked = false; data_chpt.Rows.Clear(); } } // If no titles were found, Display an error message if (drp_dvdtitle.Items.Count == 0) { MessageBox.Show( "No Title(s) found. \n\nYour Source may be copy protected, badly mastered or in a format which HandBrake does not support. \nPlease refer to the Documentation and FAQ (see Help Menu).", "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand); sourcePath = string.Empty; } UpdateSourceLabel(); // This is a bit of a hack to fix the queue editing. // If afte the scan, we find a job sitting in queueEdit, then the user has rescaned the source from the queue by clicking edit. // When this occures, we want to repopulate their old settings. if (queueEdit != null) { // Setup UI if (queueEdit.Query != null) { Preset preset = new Preset { Name = "Loaded Back From Queue", Query = queueEdit.Query, CropSettings = true, }; // Now load the preset PresetLoader.LoadPreset(this, preset); preset.Task = queueEdit.Task; this.AudioSettings.LoadTracks(preset); // Set the destination path); this.text_destination.Text = queueEdit.Task.Destination; // The x264 widgets will need updated, so do this now: x264Panel.StandardizeOptString(); x264Panel.SetCurrentSettingsInPanel(); // Set the crop label PictureSettings.SetPresetCropWarningLabel(null); } queueEdit = null; } // Enable the GUI components and enable any disabled components EnableGUI(); } catch (Exception exc) { MessageBox.Show("frmMain.cs - updateUIafterScan " + exc, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); EnableGUI(); } }
/// <summary> /// Setup the logging. /// </summary> /// <param name="encodeQueueTask"> /// The encode QueueTask. /// </param> protected void SetupLogging(QueueTask encodeQueueTask) { ShutdownFileWriter(); string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\logs"; string logFile = Path.Combine(logDir, string.Format("last_encode_log{0}.txt", GeneralUtilities.ProcessId)); string logFile2 = Path.Combine(logDir, string.Format("tmp_appReadable_log{0}.txt", GeneralUtilities.ProcessId)); try { string query = QueryGeneratorUtility.GenerateQuery(new EncodeTask(encodeQueueTask.Task), userSettingService.GetUserSetting<int>(ASUserSettingConstants.PreviewScanCount), userSettingService.GetUserSetting<int>(ASUserSettingConstants.Verbosity), userSettingService.GetUserSetting<bool>(ASUserSettingConstants.DisableLibDvdNav), userSettingService.GetUserSetting<bool>(ASUserSettingConstants.DisableQuickSyncDecoding)); this.logBuffer = new StringBuilder(); this.logBuffer.AppendLine(String.Format("CLI Query: {0}", query)); this.logBuffer.AppendLine(String.Format("User Query: {0}", encodeQueueTask.CustomQuery)); this.logBuffer.AppendLine(); // Clear the current Encode Logs) if (File.Exists(logFile)) { File.Delete(logFile); } if (File.Exists(logFile2)) { File.Delete(logFile2); } this.fileWriter = new StreamWriter(logFile) { AutoFlush = true }; this.fileWriter.WriteLine(header); this.fileWriter.WriteLine(string.Format("CLI Query: {0}", query)); this.fileWriter.WriteLine(string.Format("User Query: {0}", encodeQueueTask.CustomQuery)); this.fileWriter.WriteLine(); } catch (Exception) { if (this.fileWriter != null) { this.fileWriter.Close(); this.fileWriter.Dispose(); } throw; } }
/// <summary> /// The scan completed. /// </summary> /// <param name="job"> /// The job. /// </param> /// <param name="instance"> /// The instance. /// </param> private void ScanCompleted(QueueTask job, IHandBrakeInstance instance) { // Get an EncodeJob object for the Interop Library EncodeJob encodeJob = InteropModelCreator.GetEncodeJob(job); // Start the Encode instance.StartEncode(encodeJob, job.Configuration.PreviewScanCount); // Fire the Encode Started Event this.InvokeEncodeStarted(EventArgs.Empty); // Set the Process Priority switch (job.Configuration.ProcessPriority) { case "Realtime": Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.RealTime; break; case "High": Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High; break; case "Above Normal": Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.AboveNormal; break; case "Normal": Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.Normal; break; case "Low": Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.Idle; break; default: Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.BelowNormal; break; } }
/// <summary> /// Encode and play a sample /// </summary> public void Play() { try { this.IsEncoding = true; if (File.Exists(this.CurrentlyPlaying)) File.Delete(this.CurrentlyPlaying); } catch (Exception) { this.IsEncoding = false; this.errorService.ShowMessageBox("Unable to delete previous preview file. You may need to restart the application.", Resources.Error, MessageBoxButton.OK, MessageBoxImage.Error); } if (this.Task == null || string.IsNullOrEmpty(Task.Source)) { this.errorService.ShowMessageBox("You must first scan a source and setup your encode before creating a preview.", Resources.Error, MessageBoxButton.OK, MessageBoxImage.Error); return; } EncodeTask encodeTask = new EncodeTask(this.Task) { PreviewEncodeDuration = this.Duration, PreviewEncodeStartAt = this.SelectedPreviewImage, PointToPointMode = PointToPointMode.Preview }; // Filename handling. if (string.IsNullOrEmpty(encodeTask.Destination)) { string filename = Path.ChangeExtension(Path.GetTempFileName(), encodeTask.OutputFormat == OutputFormat.Mkv ? "m4v" : "mkv"); encodeTask.Destination = filename; this.CurrentlyPlaying = filename; } else { string directory = Path.GetDirectoryName(encodeTask.Destination) ?? string.Empty; string filename = Path.GetFileNameWithoutExtension(encodeTask.Destination); string extension = Path.GetExtension(encodeTask.Destination); string previewFilename = string.Format("{0}_preview{1}", filename, extension); string previewFullPath = Path.Combine(directory, previewFilename); encodeTask.Destination = previewFullPath; this.CurrentlyPlaying = previewFullPath; } // Setup the encode task as a preview encode encodeTask.IsPreviewEncode = true; encodeTask.PreviewEncodeStartAt = this.SelectedPreviewImage; // TODO 0 and 1 mean the same. Need to fix this as it knocks the video out of sync with the still preview. encodeTask.PreviewEncodeDuration = this.Duration; QueueTask task = new QueueTask(encodeTask, HBConfigurationFactory.Create(), this.ScannedSource.ScanPath); ThreadPool.QueueUserWorkItem(this.CreatePreview, task); }
/// <summary> /// Remove a job from the Queue. /// This method is Thread Safe /// </summary> /// <param name="job"> /// The job. /// </param> public void Remove(QueueTask job) { lock (QueueLock) { queue.Remove(job); InvokeQueueChanged(EventArgs.Empty); } }
/// <summary> /// Start with a LibHb EncodeJob Object /// </summary> /// <param name="job"> /// The job. /// </param> public void Start(QueueTask job) { this.encodeService.Start(job); }
/// <summary> /// Setup the logging. /// </summary> /// <param name="encodeQueueTask"> /// The encode QueueTask. /// </param> /// <param name="isLibhb"> /// Indicates if this is libhb that is encoding or not. /// </param> protected void SetupLogging(QueueTask encodeQueueTask, bool isLibhb) { this.ShutdownFileWriter(); string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\logs"; string logFile = Path.Combine(logDir, string.Format("last_encode_log{0}.txt", GeneralUtilities.ProcessId)); string logFile2 = Path.Combine(logDir, string.Format("tmp_appReadable_log{0}.txt", GeneralUtilities.ProcessId)); try { this.logBuffer = new StringBuilder(); this.logBuffer.AppendLine(); // Clear the current Encode Logs) if (File.Exists(logFile)) { File.Delete(logFile); } if (File.Exists(logFile2)) { File.Delete(logFile2); } lock (FileWriterLock) { this.fileWriter = new StreamWriter(logFile) { AutoFlush = true }; this.fileWriter.WriteLine(this.header); this.fileWriter.WriteLine(); } } catch (Exception) { if (this.fileWriter != null) { lock (FileWriterLock) { this.fileWriter.Flush(); this.fileWriter.Close(); this.fileWriter.Dispose(); } } throw; } }
/// <summary> /// Reset the job state to waiting. /// </summary> /// <param name="task"> /// The task. /// </param> public void RetryJob(QueueTask task) { task.Status = QueueItemStatus.Waiting; this.queueProcessor.BackupQueue(null); this.JobsPending = string.Format("{0} jobs pending", this.queueProcessor.Count); }
/// <summary> /// Edit this Job /// </summary> /// <param name="task"> /// The task. /// </param> public void EditJob(QueueTask task) { MessageBoxResult result = this.errorService.ShowMessageBox( "Are you sure you wish to edit this job? It will be removed from the queue and sent to the main window.", "Modify Job?", MessageBoxButton.YesNo, MessageBoxImage.Question); if (result != MessageBoxResult.Yes) { return; } // Remove the job if it is not already encoding. Let the user decide if they want to cancel or not. this.RemoveJob(task); // Pass a copy of the job back to the Main Screen IMainViewModel mvm = IoC.Get<IMainViewModel>(); mvm.EditQueueJob(new EncodeTask(task.Task)); }
/// <summary> /// Start with a LibHb EncodeJob Object /// </summary> /// <param name="job"> /// The job. /// </param> /// <param name="enableLogging"> /// The enable Logging. /// </param> public void Start(QueueTask job, bool enableLogging) { ThreadPool.QueueUserWorkItem( delegate { this.Service.StartEncode(job, enableLogging); }); }
/// <summary> /// The equals. /// </summary> /// <param name="other"> /// The other. /// </param> /// <returns> /// The <see cref="bool"/>. /// </returns> protected bool Equals(QueueTask other) { return(Equals(this.ScannedSourcePath, other.ScannedSourcePath) && Equals(this.Task, other.Task) && this.status == other.status); }
/// <summary> /// Add a job to the Queue. /// This method is Thread Safe. /// </summary> /// <param name="job"> /// The encode Job object. /// </param> public void Add(QueueTask job) { lock (QueueLock) { // Tag the job with an ID job.Id = lastJobId++; queue.Add(job); InvokeQueueChanged(EventArgs.Empty); } }
/// <summary> /// Execute a HandBrakeCLI process. /// This should only be called from the UI thread. /// </summary> /// <param name="encodeQueueTask"> /// The encodeQueueTask. /// </param> public void Start(QueueTask encodeQueueTask) { try { if (this.IsEncoding) { throw new GeneralApplicationException("HandBrake is already encodeing.", "Please try again in a minute", null); } this.IsEncoding = true; this.currentTask = encodeQueueTask; if (encodeQueueTask.Configuration.IsLoggingEnabled) { try { this.SetupLogging(currentTask); } catch (Exception) { this.IsEncoding = false; throw; } } // Make sure the path exists, attempt to create it if it doesn't this.VerifyEncodeDestinationPath(currentTask); string handbrakeCLIPath = Path.Combine(Application.StartupPath, "HandBrakeCLI.exe"); // TODO tidy this code up, it's kinda messy. string query = this.currentTask.Task.IsPreviewEncode ? QueryGeneratorUtility.GeneratePreviewQuery( new EncodeTask(this.currentTask.Task), encodeQueueTask.Configuration, this.currentTask.Task.PreviewEncodeDuration, this.currentTask.Task.PreviewEncodeStartAt) : QueryGeneratorUtility.GenerateQuery(new EncodeTask(this.currentTask.Task), encodeQueueTask.Configuration); ProcessStartInfo cliStart = new ProcessStartInfo(handbrakeCLIPath, query) { RedirectStandardOutput = true, RedirectStandardError = encodeQueueTask.Configuration.IsLoggingEnabled, UseShellExecute = false, CreateNoWindow = true }; this.HbProcess = new Process { StartInfo = cliStart }; this.HbProcess.Start(); this.startTime = DateTime.Now; if (encodeQueueTask.Configuration.IsLoggingEnabled) { this.HbProcess.ErrorDataReceived += this.HbProcErrorDataReceived; this.HbProcess.BeginErrorReadLine(); } this.HbProcess.OutputDataReceived += HbProcess_OutputDataReceived; this.HbProcess.BeginOutputReadLine(); this.processId = this.HbProcess.Id; // Set the process Priority if (this.processId != -1) { this.HbProcess.EnableRaisingEvents = true; this.HbProcess.Exited += this.HbProcessExited; } // Set the Process Priority switch (encodeQueueTask.Configuration.ProcessPriority) { case "Realtime": this.HbProcess.PriorityClass = ProcessPriorityClass.RealTime; break; case "High": this.HbProcess.PriorityClass = ProcessPriorityClass.High; break; case "Above Normal": this.HbProcess.PriorityClass = ProcessPriorityClass.AboveNormal; break; case "Normal": this.HbProcess.PriorityClass = ProcessPriorityClass.Normal; break; case "Low": this.HbProcess.PriorityClass = ProcessPriorityClass.Idle; break; default: this.HbProcess.PriorityClass = ProcessPriorityClass.BelowNormal; break; } // Fire the Encode Started Event this.InvokeEncodeStarted(EventArgs.Empty); } catch (Exception exc) { encodeQueueTask.Status = QueueItemStatus.Error; this.IsEncoding = false; this.InvokeEncodeCompleted( new EncodeCompletedEventArgs( false, exc, "An Error occured when trying to encode this source. ", this.currentTask.Task.Destination)); throw; } }
/// <summary> /// Reset a Queued Item from Error or Completed to Waiting /// </summary> /// <param name="job"> /// The job. /// </param> public void ResetJobStatusToWaiting(QueueTask job) { if (job.Status != QueueItemStatus.Error && job.Status != QueueItemStatus.Completed) { throw new GeneralApplicationException("Job Error", "Unable to reset job status as it is not in an Error or Completed state", null); } job.Status = QueueItemStatus.Waiting; }
/// <summary> /// The equals. /// </summary> /// <param name="other"> /// The other. /// </param> /// <returns> /// The <see cref="bool"/>. /// </returns> protected bool Equals(QueueTask other) { return(Equals(this.ScannedSource, other.ScannedSource) && this.CustomQuery.Equals(other.CustomQuery) && Equals(this.Task, other.Task) && this.status == other.status); }
/// <summary> /// Start with a LibHb EncodeJob Object /// </summary> /// <param name="job"> /// The job. /// </param> public void Start(QueueTask job) { // Setup this.startTime = DateTime.Now; this.loggingEnabled = job.Configuration.IsLoggingEnabled; this.currentTask = job; // Create a new HandBrake instance // Setup the HandBrake Instance instance = new HandBrakeInstance(); instance.Initialize(1); instance.EncodeCompleted += this.InstanceEncodeCompleted; instance.EncodeProgress += this.InstanceEncodeProgress; try { // Sanity Checking and Setup if (this.IsEncoding) { throw new Exception("HandBrake is already encoding."); } this.IsEncoding = true; // Enable logging if required. if (job.Configuration.IsLoggingEnabled) { try { this.SetupLogging(job); } catch (Exception) { this.IsEncoding = false; throw; } } // Verify the Destination Path Exists, and if not, create it. this.VerifyEncodeDestinationPath(job); // We have to scan the source again but only the title so the HandBrake instance is initialised correctly. // Since the UI sends the crop params down, we don't have to do all the previews. instance.StartScan(job.Task.Source, job.Configuration.PreviewScanCount, job.Task.Title); instance.ScanCompleted += delegate { ScanCompleted(job, instance); }; } catch (Exception exc) { this.InvokeEncodeCompleted(new EncodeCompletedEventArgs(false, exc, "An Error has occured.", this.currentTask.Task.Destination)); } }
public static QueueTask GenerateFullQueryForBatchTitle(frmMain mainWindow, BatchTitle batchTitle) { int? angle = null; if (mainWindow.drop_angle.SelectedItem != null) { string selectedAngleStr = mainWindow.drop_angle.SelectedItem.ToString(); int tempAngle; if (int.TryParse(selectedAngleStr, out tempAngle)) { angle = tempAngle; } } string sourcePath = mainWindow.sourcePath; // Create the CLI Query string query = string.Empty; query += SourceQuery(sourcePath, batchTitle, angle); query += DestinationQuery(batchTitle); query += GenerateTabbedComponentsQuery(batchTitle, mainWindow, true, QueryPictureSettingsMode.UserInterfaceSettings, 0, 0); // Create the Queue Task and setup the EncodeTask model object. Preset preset = null; if (mainWindow.treeView_presets.SelectedNode != null) { preset = mainWindow.treeView_presets.SelectedNode.Tag as Preset; } bool isCustom = true; if (preset != null && preset.IsBuildIn) { isCustom = false; } EncodeTask task = CreateEncodeTaskObjectFromBatch(batchTitle, mainWindow); QueueTask queueTask = new QueueTask(query) { Source = task.Source, Destination = task.Destination, Title = mainWindow.GetTitle(), CustomQuery = (mainWindow.rtf_query.Text != string.Empty) || isCustom, Task = task, Query = query, }; return queueTask; }
/// <summary> /// Reset the job state to waiting. /// </summary> /// <param name="task"> /// The task. /// </param> public void RetryJob(QueueTask task) { task.Status = QueueItemStatus.Waiting; this.queueProcessor.QueueManager.BackupQueue(null); }
/// <summary> /// Start with a LibHb EncodeJob Object /// </summary> /// <param name="job"> /// The job. /// </param> /// <param name="enableLogging"> /// The enable Logging. /// </param> public void Start(QueueTask job, bool enableLogging) { this.encodeService.Start(job, enableLogging); }
/// <summary> /// Verify the Encode Destination path exists and if not, create it. /// </summary> /// <param name="task"> /// The task. /// </param> /// <exception cref="Exception"> /// If the creation fails, an exception is thrown. /// </exception> protected void VerifyEncodeDestinationPath(QueueTask task) { // Make sure the path exists, attempt to create it if it doesn't try { string path = Directory.GetParent(task.Task.Destination).ToString(); if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } } catch (Exception exc) { throw new GeneralApplicationException( "Unable to create directory for the encoded output.", "Please verify that you have a valid path.", exc); } }
/// <summary> /// Start with a LibHb EncodeJob Object /// </summary> /// <param name="job"> /// The job. /// </param> public void Start(QueueTask job) { try { // Setup this.startTime = DateTime.Now; this.currentTask = job; // Create a new HandBrake instance // Setup the HandBrake Instance HandBrakeUtils.MessageLogged += this.HandBrakeInstanceMessageLogged; HandBrakeUtils.ErrorLogged += this.HandBrakeInstanceErrorLogged; this.instance = HandBrakeInstanceManager.GetEncodeInstance(job.Configuration.Verbosity); this.instance.EncodeCompleted += this.InstanceEncodeCompleted; this.instance.EncodeProgress += this.InstanceEncodeProgress; // Sanity Checking and Setup if (this.IsEncoding) { throw new Exception("HandBrake is already encoding."); } this.IsEncoding = true; this.SetupLogging(job, true); // Verify the Destination Path Exists, and if not, create it. this.VerifyEncodeDestinationPath(job); ServiceLogMessage("Starting Encode ..."); // Get an EncodeJob object for the Interop Library instance.StartEncode(EncodeFactory.Create(job.Task, job.Configuration)); // Fire the Encode Started Event this.InvokeEncodeStarted(System.EventArgs.Empty); // Set the Process Priority switch (job.Configuration.ProcessPriority) { case "Realtime": Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.RealTime; break; case "High": Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High; break; case "Above Normal": Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.AboveNormal; break; case "Normal": Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.Normal; break; case "Low": Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.Idle; break; default: Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.BelowNormal; break; } } catch (Exception exc) { this.IsEncoding = false; ServiceLogMessage("Failed to start encoding ..." + Environment.NewLine + exc); this.InvokeEncodeCompleted(new EventArgs.EncodeCompletedEventArgs(false, exc, "Unable to start encoding", job.Task.Source)); } }
/// <summary> /// Take a job from the Queue, rescan it, and reload the GUI for that job. /// </summary> /// <param name="job"> /// The job. /// </param> public void RecievingJob(QueueTask job) { // Reset this.currentlySelectedPreset = null; x264Panel.Reset2Defaults(); // Scan queueEdit = job; // Nasty but will do for now. TODO StartScan(job.Task.Source, job.Task.Title); }
/* * TODO: This conversion class needs to be finished off before libencode will work. */ /// <summary> /// Get an EncodeJob model for a LibHB Encode. /// </summary> /// <param name="task"> /// The task. /// </param> /// <returns> /// An Interop.EncodeJob model. /// </returns> public static EncodeJob GetEncodeJob(QueueTask task) { // Sanity Checking if (task == null || task.Task == null) { return null; } // The current Job Configuration EncodeTask work = task.Task; // Which will be converted to this EncodeJob Model. EncodeJob job = new EncodeJob(); EncodingProfile profile = new EncodingProfile(); job.EncodingProfile = profile; profile.Anamorphic = work.Anamorphic; profile.AudioEncodings = new List<AudioEncoding>(); job.ChosenAudioTracks = new List<int>(); foreach (AudioTrack track in work.AudioTracks) { AudioEncoding newTrack = new AudioEncoding { Bitrate = track.Bitrate, Drc = track.DRC, Gain = track.Gain, Encoder = Converters.GetCliAudioEncoder(track.Encoder), InputNumber = track.Track.HasValue ? track.Track.Value : 0, Mixdown = Converters.GetCliMixDown(track.MixDown), SampleRateRaw = GetSampleRateRaw(track.SampleRate), }; profile.AudioEncodings.Add(newTrack); if (track.Track != null) { job.ChosenAudioTracks.Add(track.Track.Value); } } profile.Cropping = new Cropping { Top = work.Cropping.Top, Bottom = work.Cropping.Bottom, Left = work.Cropping.Left, Right = work.Cropping.Right }; profile.CroppingType = CroppingType.Custom; // TODO deal with this better profile.CustomDecomb = work.CustomDecomb; profile.CustomDeinterlace = work.CustomDeinterlace; profile.CustomDenoise = work.CustomDenoise; profile.CustomDetelecine = work.CustomDetelecine; profile.Deblock = work.Deblock; profile.Decomb = work.Decomb; profile.Deinterlace = work.Deinterlace; profile.Denoise = work.Denoise; profile.Detelecine = work.Detelecine; profile.DisplayWidth = work.DisplayWidth.HasValue ? int.Parse(Math.Round(work.DisplayWidth.Value, 0).ToString()) : 0; profile.Framerate = work.Framerate.HasValue ? work.Framerate.Value : 0; profile.Grayscale = work.Grayscale; profile.Height = work.Height.HasValue ? work.Height.Value : 0; profile.IPod5GSupport = work.IPod5GSupport; profile.IncludeChapterMarkers = work.IncludeChapterMarkers; profile.KeepDisplayAspect = work.KeepDisplayAspect; profile.LargeFile = work.LargeFile; profile.MaxHeight = work.MaxHeight.HasValue ? work.MaxHeight.Value : 0; profile.MaxWidth = work.MaxWidth.HasValue ? work.MaxWidth.Value : 0; profile.Modulus = work.Modulus.HasValue ? work.Modulus.Value : 16; profile.Optimize = work.OptimizeMP4; switch (work.OutputFormat) { case OutputFormat.Mp4: case OutputFormat.M4V: profile.OutputFormat = Container.Mp4; break; case OutputFormat.Mkv: profile.OutputFormat = Container.Mkv; break; } profile.ConstantFramerate = work.FramerateMode == FramerateMode.CFR; profile.PixelAspectX = work.PixelAspectX; profile.PixelAspectY = work.PixelAspectY; switch (work.OutputFormat) { case OutputFormat.Mp4: profile.PreferredExtension = OutputExtension.Mp4; break; case OutputFormat.M4V: profile.PreferredExtension = OutputExtension.M4v; break; } profile.Quality = work.Quality.HasValue ? work.Quality.Value : 0; profile.UseDisplayWidth = true; profile.VideoBitrate = work.VideoBitrate.HasValue ? work.VideoBitrate.Value : 0; profile.VideoEncodeRateType = work.VideoEncodeRateType; profile.VideoEncoder = Converters.GetVideoEncoder(work.VideoEncoder); profile.Width = work.Width.HasValue ? work.Width.Value : 0; profile.X264Options = work.AdvancedEncoderOptions; if (work.PointToPointMode == PointToPointMode.Chapters) { job.ChapterStart = work.StartPoint; job.ChapterEnd = work.EndPoint; } job.Angle = work.Angle; job.EncodingProfile = profile; if (work.PointToPointMode == PointToPointMode.Frames) { job.FramesEnd = work.EndPoint; job.FramesStart = work.StartPoint; } job.CustomChapterNames = work.ChapterNames.Select(item => item.ChapterName).ToList(); job.UseDefaultChapterNames = work.IncludeChapterMarkers; job.OutputPath = work.Destination; switch (work.PointToPointMode) { case PointToPointMode.Chapters: job.RangeType = VideoRangeType.Chapters; break; case PointToPointMode.Seconds: job.RangeType = VideoRangeType.Seconds; break; case PointToPointMode.Frames: job.RangeType = VideoRangeType.Frames; break; } if (work.PointToPointMode == PointToPointMode.Seconds) { job.SecondsEnd = work.EndPoint; job.SecondsStart = work.StartPoint; } job.SourcePath = work.Source; // job.SourceType = work.Type; job.Title = work.Title; // TODO Setup subtitles job.Subtitles = new Subtitles { SourceSubtitles = new List<SourceSubtitle>(), SrtSubtitles = new List<SrtSubtitle>() }; //foreach (SubtitleTrack track in work.SubtitleTracks) //{ // // TODO //} return job; }
/// <summary> /// Remove a Job from the queue /// </summary> /// <param name="task"> /// The Job to remove from the queue /// </param> public void RemoveJob(QueueTask task) { if (task.Status == QueueItemStatus.InProgress) { MessageBoxResult result = this.errorService.ShowMessageBox( "This encode is currently in progress. If you delete it, the encode will be stoped. Are you sure you wish to proceed?", "Warning", MessageBoxButton.YesNo, MessageBoxImage.Question); if (result == MessageBoxResult.Yes) { this.queueProcessor.QueueManager.Remove(task); } } else { this.queueProcessor.QueueManager.Remove(task); } this.JobsPending = string.Format("{0} jobs pending", this.queueProcessor.QueueManager.Count); }
private bool AddItemToQueue(bool showError) { string query = QueryGenerator.GenerateFullQuery(this); if (!string.IsNullOrEmpty(rtf_query.Text)) query = rtf_query.Text; // If we have a custom query, then we'll want to figure out what the new source and destination is, otherwise we'll just use the gui components. string jobSourcePath = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetSourceFromQuery(rtf_query.Text) : sourcePath; string jobDestination = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetDestinationFromQuery(rtf_query.Text) : text_destination.Text; // Make sure we have a Source and Destination. if (string.IsNullOrEmpty(jobSourcePath) || string.IsNullOrEmpty(jobDestination)) { if (showError) MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); return false; } // Make sure we don't have a duplciate on the queue. if (this.queueProcessor.QueueManager.CheckForDestinationPathDuplicates(jobDestination)) { if (showError) { DialogResult result; result = MessageBox.Show( string.Format( "There is already a queue item for this destination path.\nDestination Path: {0} \n\nIf you continue, the encode will be overwritten. Do you wish to continue?", jobDestination), "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning); if (result != DialogResult.Yes) return false; } else { return false; } } // Add the job. QueueTask task = new QueueTask(query) { Title = this.GetTitle(), Source = jobSourcePath, Destination = jobDestination, CustomQuery = (this.rtf_query.Text != string.Empty) }; this.queueProcessor.QueueManager.Add(task); lbl_encode.Text = this.queueProcessor.QueueManager.Count + " encode(s) pending in the queue"; return true; }
/// <summary> /// Add the current task to the queue. /// </summary> public void AddToQueue() { if (this.ScannedSource == null || string.IsNullOrEmpty(this.ScannedSource.ScanPath) || this.ScannedSource.Titles.Count == 0) { this.errorService.ShowMessageBox("You must first scan a source and setup your job before adding to the queue.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } QueueTask task = new QueueTask { Task = new EncodeTask(this.CurrentTask) }; if (!this.queueProcessor.QueueManager.CheckForDestinationPathDuplicates(task.Task.Destination)) { this.queueProcessor.QueueManager.Add(task); } else { this.errorService.ShowMessageBox("There are jobs on the queue with the same destination path. Please choose a different path for this job.", "Error", MessageBoxButton.OK, MessageBoxImage.Warning); } if (!this.IsEncoding) { this.ProgramStatusLabel = string.Format("{0} Encodes Pending", this.queueProcessor.QueueManager.Count); } }
/// <summary> /// Toolbar - Start The Encode /// </summary> /// <param name="sender"> /// The sender. /// </param> /// <param name="e"> /// The e. /// </param> private void btn_start_Click(object sender, EventArgs e) { if (btn_start.Text == "Stop") { DialogResult result = !userSettingService.GetUserSetting<bool>(ASUserSettingConstants.ShowCLI) ? MessageBox.Show( "Are you sure you wish to cancel the encode?\n\nPlease note: Stopping this encode will render the file unplayable. ", "Cancel Encode?", MessageBoxButtons.YesNo, MessageBoxIcon.Question) : MessageBox.Show( "Are you sure you wish to cancel the encode?", "Cancel Encode?", MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (result == DialogResult.Yes) { // Pause The Queue this.queueProcessor.Pause(); if (userSettingService.GetUserSetting<bool>(ASUserSettingConstants.ShowCLI)) this.queueProcessor.EncodeService.SafelyStop(); else this.queueProcessor.EncodeService.Stop(); } } else { // If we have a custom query, then we'll want to figure out what the new source and destination is, otherwise we'll just use the gui components. string jobSourcePath = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetSourceFromQuery(rtf_query.Text) : sourcePath; string jobDestination = !string.IsNullOrEmpty(rtf_query.Text) ? Main.GetDestinationFromQuery(rtf_query.Text) : text_destination.Text; if (this.queueProcessor.QueueManager.Count != 0 || (!string.IsNullOrEmpty(jobSourcePath) && !string.IsNullOrEmpty(jobDestination))) { string generatedQuery = QueryGenerator.GenerateFullQuery(this); string specifiedQuery = rtf_query.Text != string.Empty ? rtf_query.Text : QueryGenerator.GenerateFullQuery(this); string query = string.Empty; // Check to make sure the generated query matches the GUI settings if (this.userSettingService.GetUserSetting<bool>(UserSettingConstants.PromptOnUnmatchingQueries) && !string.IsNullOrEmpty(specifiedQuery) && generatedQuery != specifiedQuery) { DialogResult result = MessageBox.Show("The query under the \"Query Editor\" tab " + "does not match the current GUI settings.\n\nBecause the manual query takes " + "priority over the GUI, your recently updated settings will not be taken " + "into account when encoding this job." + Environment.NewLine + Environment.NewLine + "Do you want to replace the manual query with the updated GUI-generated query?", "Manual Query does not Match GUI", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Asterisk, MessageBoxDefaultButton.Button3); switch (result) { case DialogResult.Yes: // Replace the manual query with the generated one query = generatedQuery; rtf_query.Text = generatedQuery; break; case DialogResult.No: // Use the manual query query = specifiedQuery; break; case DialogResult.Cancel: // Don't start the encode return; } } else { query = specifiedQuery; } DialogResult overwrite = DialogResult.Yes; if (!string.IsNullOrEmpty(jobDestination) && File.Exists(jobDestination)) { overwrite = MessageBox.Show( "The destination file already exists. Are you sure you want to overwrite it?", "Overwrite File?", MessageBoxButtons.YesNo, MessageBoxIcon.Question); } if (overwrite == DialogResult.Yes) { QueueTask task = new QueueTask(query) { Title = this.GetTitle(), Source = jobSourcePath, Destination = jobDestination, CustomQuery = (this.rtf_query.Text != string.Empty) }; if (this.queueProcessor.QueueManager.Count == 0) this.queueProcessor.QueueManager.Add(task); queueWindow.SetQueue(); if (this.queueProcessor.QueueManager.Count > 1) queueWindow.Show(false); SetEncodeStarted(); // Encode is running, so setup the GUI appropriately this.queueProcessor.Start(); // Start The Queue Encoding Process } this.Focus(); } else if (string.IsNullOrEmpty(sourcePath) || string.IsNullOrEmpty(text_destination.Text)) MessageBox.Show("No source or destination selected.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); } }