// --------------------------------------------------------------------------------------------------------------------
//
// 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;
}
}
}
}