// -------------------------------------------------------------------------------------------------------------------- // // This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. // // // The HandBrake Queue // // -------------------------------------------------------------------------------------------------------------------- namespace HandBrake.ApplicationServices.Services { using System; using System.Diagnostics; using System.IO; using System.Windows.Forms; using Caliburn.Micro; using HandBrake.ApplicationServices.EventArgs; using HandBrake.ApplicationServices.Functions; using HandBrake.ApplicationServices.Model; using HandBrake.ApplicationServices.Services.Interfaces; /// /// The HandBrake Queue /// public class QueueProcessor : IQueueProcessor { /// /// The User Setting Service /// private static IUserSettingService userSettingService = IoC.Get(); /// /// Initializes a new instance of the class. /// /// /// The queue manager. /// /// /// The encode Service. /// /// /// Services are not setup /// public QueueProcessor(IQueueManager queueManager, IEncode encodeService) { this.QueueManager = queueManager; this.EncodeService = encodeService; if (this.QueueManager == null) { throw new ArgumentNullException("queueManager"); } if (this.QueueManager == null) { throw new ArgumentNullException("queueManager"); } } /// /// Initializes a new instance of the class. /// This call also initializes the Encode and QueueManager services /// /// /// The instance id. /// public QueueProcessor(int instanceId) { this.EncodeService = File.Exists("hb.dll") ? (IEncode)new LibEncode() : new Encode(); this.QueueManager = new QueueManager(instanceId); } #region Events /// /// Queue Progess Status /// /// /// The sender. /// /// /// The QueueProgressEventArgs. /// public delegate void QueueProgressStatus(object sender, QueueProgressEventArgs e); /// /// Fires when the Queue has started /// public event QueueProgressStatus JobProcessingStarted; /// /// Fires when a pause to the encode queue has been requested. /// public event EventHandler QueuePaused; /// /// Fires when the entire encode queue has completed. /// public event EventHandler QueueCompleted; /// /// Invoke the JobProcessingStarted event /// /// /// The QueueProgressEventArgs. /// private void InvokeJobProcessingStarted(QueueProgressEventArgs e) { QueueProgressStatus handler = this.JobProcessingStarted; if (handler != null) { handler(this, e); } } /// /// Invoke the QueuePaused event /// /// /// The EventArgs. /// private void InvokeQueuePaused(EventArgs e) { EventHandler handler = this.QueuePaused; if (handler != null) { handler(this, e); } } /// /// Invoke the QueueCompleted event. /// /// /// The EventArgs. /// private void InvokeQueueCompleted(EventArgs e) { this.IsProcessing = false; EventHandler handler = this.QueueCompleted; if (handler != null) { handler(this, e); } } #endregion #region Properties /// /// Gets a value indicating whether IsProcessing. /// public bool IsProcessing { get; private set; } /// /// Gets the IEncodeService instance. /// public IEncode EncodeService { get; private set; } /// /// Gets the IQueueManager instance. /// public IQueueManager QueueManager { get; private set; } #endregion /// /// Starts encoding the first job in the queue and continues encoding until all jobs /// have been encoded. /// public void Start() { if (IsProcessing) { throw new Exception("Already Processing the Queue"); } IsProcessing = true; this.EncodeService.EncodeCompleted += this.EncodeServiceEncodeCompleted; this.ProcessNextJob(); } /// /// Requests a pause of the encode queue. /// public void Pause() { this.InvokeQueuePaused(EventArgs.Empty); this.IsProcessing = false; } /// /// After an encode is complete, move onto the next job. /// /// /// The sender. /// /// /// The EncodeCompletedEventArgs. /// private void EncodeServiceEncodeCompleted(object sender, EncodeCompletedEventArgs e) { this.QueueManager.LastProcessedJob.Status = QueueItemStatus.Completed; // Clear the completed item of the queue if the setting is set. if (userSettingService.GetUserSetting(ASUserSettingConstants.ClearCompletedFromQueue)) { this.QueueManager.ClearCompleted(); } // Growl if (userSettingService.GetUserSetting(ASUserSettingConstants.GrowlEncode)) GrowlCommunicator.Notify("Encode Completed", "Put down that cocktail...\nyour Handbrake encode is done."); if (!e.Successful) { this.QueueManager.LastProcessedJob.Status = QueueItemStatus.Error; this.Pause(); } // Handling Log Data this.EncodeService.ProcessLogs(this.QueueManager.LastProcessedJob.Task.Destination); // Post-Processing if (e.Successful) { SendToApplication(this.QueueManager.LastProcessedJob.Task.Destination); } // Move onto the next job. if (this.IsProcessing) { this.ProcessNextJob(); } else { this.EncodeService.EncodeCompleted -= this.EncodeServiceEncodeCompleted; this.InvokeQueueCompleted(EventArgs.Empty); this.QueueManager.BackupQueue(string.Empty); } } /// /// Run through all the jobs on the queue. /// private void ProcessNextJob() { if (this.EncodeService.IsEncoding || !this.IsProcessing) { // We don't want to try start a second encode, so just return out. The event will trigger the next encode automatically. // Also, we don't want to start a new encode if we are paused. return; } QueueTask job = this.QueueManager.GetNextJobForProcessing(); if (job != null) { this.EncodeService.Start(job, true); this.InvokeJobProcessingStarted(new QueueProgressEventArgs(job)); } else { // No more jobs to process, so unsubscribe the event this.EncodeService.EncodeCompleted -= this.EncodeServiceEncodeCompleted; // Fire the event to tell connected services. this.InvokeQueueCompleted(EventArgs.Empty); // Run the After encode completeion work Finish(); } } /// /// Send a file to a 3rd party application after encoding has completed. /// /// The file path private static void SendToApplication(string file) { if (userSettingService.GetUserSetting(ASUserSettingConstants.SendFile) && !string.IsNullOrEmpty(userSettingService.GetUserSetting(ASUserSettingConstants.SendFileTo))) { string args = string.Format("{0} \"{1}\"", userSettingService.GetUserSetting(ASUserSettingConstants.SendFileToArgs), file); ProcessStartInfo vlc = new ProcessStartInfo(userSettingService.GetUserSetting(ASUserSettingConstants.SendFileTo), args); Process.Start(vlc); } } /// /// Perform an action after an encode. e.g a shutdown, standby, restart etc. /// private static void Finish() { // Growl if (userSettingService.GetUserSetting(ASUserSettingConstants.GrowlQueue)) { GrowlCommunicator.Notify("Queue Completed", "Put down that cocktail...\nyour Handbrake queue is done."); } // Do something whent he encode ends. switch (userSettingService.GetUserSetting(ASUserSettingConstants.WhenCompleteAction)) { case "Shutdown": Process.Start("Shutdown", "-s -t 60"); break; case "Log off": Win32.ExitWindowsEx(0, 0); break; case "Suspend": Application.SetSuspendState(PowerState.Suspend, true, true); break; case "Hibernate": Application.SetSuspendState(PowerState.Hibernate, true, true); break; case "Lock System": Win32.LockWorkStation(); break; case "Quit HandBrake": Application.Exit(); break; default: break; } } } }