// --------------------------------------------------------------------------------------------------------------------
//
// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License.
//
//
// Defines the QueueRecoveryHelper type.
//
// --------------------------------------------------------------------------------------------------------------------
namespace HandBrakeWPF.Helpers
{
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows;
using System.Xml.Serialization;
using HandBrake.ApplicationServices.Model;
using HandBrake.ApplicationServices.Utilities;
using HandBrakeWPF.Services.Interfaces;
using HandBrakeWPF.Services.Queue.Model;
using HandBrakeWPF.Utilities;
using IQueueProcessor = HandBrakeWPF.Services.Queue.Interfaces.IQueueProcessor;
///
/// Queue Recovery Helper
///
public class QueueRecoveryHelper
{
///
/// Check if the queue recovery file contains records.
/// If it does, it means the last queue did not complete before HandBrake closed.
/// So, return a boolean if true.
///
///
/// True if there is a queue to recover.
///
public static List CheckQueueRecovery()
{
try
{
XmlSerializer Ser = new XmlSerializer(typeof(List));
string tempPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"HandBrake\");
List queueFiles = new List();
List removeFiles = new List();
DirectoryInfo info = new DirectoryInfo(tempPath);
IEnumerable logFiles = info.GetFiles("*.xml").Where(f => f.Name.StartsWith("hb_queue_recovery"));
foreach (FileInfo file in logFiles)
{
using (FileStream strm = new FileStream(file.FullName, FileMode.Open, FileAccess.Read))
{
List list = Ser.Deserialize(strm) as List;
if (list != null && list.Count == 0)
{
removeFiles.Add(file.FullName);
}
if (list != null && list.Count != 0)
{
List tasks = list.Where(l => l.Status != QueueItemStatus.Completed).ToList();
if (tasks.Count != 0)
{
queueFiles.Add(file.Name);
}
}
}
}
// Cleanup old/unused queue files for now.
foreach (string file in removeFiles)
{
Match m = Regex.Match(file, @"([0-9]+).xml");
if (m.Success)
{
int processId = int.Parse(m.Groups[1].ToString());
if (GeneralUtilities.IsPidACurrentHandBrakeInstance(processId))
{
continue;
}
}
File.Delete(file);
}
return queueFiles;
}
catch (Exception)
{
return new List(); // Keep quiet about the error.
}
}
///
/// Recover a queue from file.
///
///
/// The encode Queue.
///
///
/// The error Service.
///
public static bool RecoverQueue(IQueueProcessor encodeQueue, IErrorService errorService)
{
string appDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"HandBrake\");
List queueFiles = CheckQueueRecovery();
MessageBoxResult result = MessageBoxResult.None;
if (queueFiles.Count == 1)
{
result = errorService.ShowMessageBox(
"HandBrake has detected unfinished items on the queue from the last time the application was launched. Would you like to recover these?",
"Queue Recovery Possible", MessageBoxButton.YesNo, MessageBoxImage.Question);
}
else if (queueFiles.Count > 1)
{
result = MessageBox.Show(
"HandBrake has detected multiple unfinished queue files. These will be from multiple instances of HandBrake running. Would you like to recover all unfinished jobs?",
"Queue Recovery Possible", MessageBoxButton.YesNo, MessageBoxImage.Question);
}
if (result == MessageBoxResult.Yes)
{
bool isRecovered = false;
foreach (string file in queueFiles)
{
// Skip over the file if it belongs to another HandBrake instance.
Match m = Regex.Match(file, @"([0-9]+).xml");
if (m.Success)
{
int processId = int.Parse(m.Groups[1].ToString());
if (processId != GeneralUtilities.ProcessId && GeneralUtilities.IsPidACurrentHandBrakeInstance(processId))
{
continue;
}
}
// Recover the Queue
encodeQueue.RestoreQueue(appDataPath + file);
isRecovered = true;
// Cleanup
if (!file.Contains(GeneralUtilities.ProcessId.ToString(CultureInfo.InvariantCulture)))
{
try
{
// Once we load it in, remove it as we no longer need it.
File.Delete(Path.Combine(appDataPath, file));
}
catch (Exception)
{
// Keep quite, nothing much we can do if there are problems.
// We will continue processing files.
}
}
}
return isRecovered;
}
else
{
foreach (string file in queueFiles)
{
if (File.Exists(Path.Combine(appDataPath, file)))
{
// Check that the file doesn't belong to another running instance.
Match m = Regex.Match(file, @"([0-9]+).xml");
if (m.Success)
{
int processId = int.Parse(m.Groups[1].ToString());
if (GeneralUtilities.IsPidACurrentHandBrakeInstance(processId))
{
continue;
}
}
// Delete it if it doesn't
File.Delete(Path.Combine(appDataPath, file));
}
}
return false;
}
}
}
}