// --------------------------------------------------------------------------------------------------------------------
//
// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License.
//
//
// The About View Model
//
// --------------------------------------------------------------------------------------------------------------------
namespace HandBrakeWPF.ViewModels
{
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Threading;
using System.Windows;
using HandBrake.ApplicationServices;
using HandBrake.ApplicationServices.Model;
using HandBrake.ApplicationServices.Model.Encoding;
using HandBrake.ApplicationServices.Services.Interfaces;
using HandBrakeWPF.Factories;
using HandBrakeWPF.Services;
using HandBrakeWPF.Services.Interfaces;
using HandBrakeWPF.ViewModels.Interfaces;
///
/// The About View Model
///
public class PreviewViewModel : ViewModelBase, IPreviewViewModel
{
#region Constants and Fields
///
/// Backing field for the encode service.
///
private readonly IEncodeServiceWrapper encodeService;
///
/// The error service
///
private readonly IErrorService errorService;
///
/// The user Setting Service
///
private readonly IUserSettingService userSettingService;
///
/// The percentage.
///
private string percentage;
///
/// The percentage value.
///
private double percentageValue;
///
/// The Backing field for IsEncoding
///
private bool isEncoding;
///
/// Backing field for use system default player
///
private bool useSystemDefaultPlayer;
#endregion
#region Constructors and Destructors
///
/// Initializes a new instance of the class.
///
///
/// The error Service.
///
///
/// The user Setting Service.
///
public PreviewViewModel(IErrorService errorService, IUserSettingService userSettingService)
{
// Preview needs a seperate instance rather than the shared singleton. This could maybe do with being refactored at some point
this.encodeService = new EncodeServiceWrapper(userSettingService);
this.errorService = errorService;
this.userSettingService = userSettingService;
this.Title = "Preview";
this.Percentage = "0.00%";
this.PercentageValue = 0;
this.StartAt = 1;
this.Duration = 30;
this.CanPlay = true;
UseSystemDefaultPlayer = userSettingService.GetUserSetting(UserSettingConstants.DefaultPlayer);
this.Duration = userSettingService.GetUserSetting(UserSettingConstants.LastPreviewDuration);
}
#endregion
#region Properties
///
/// Gets or sets Task.
///
public EncodeTask Task { get; set; }
///
/// Gets AvailableDurations.
///
public IEnumerable AvailableDurations
{
get
{
return new List { 5, 10, 30, 45, 60, 75, 90, 105, 120, 150, 180, 210, 240 };
}
}
///
/// Gets or sets Duration.
///
public int Duration { get; set; }
///
/// Gets or sets Percentage.
///
public string Percentage
{
get
{
return this.percentage;
}
set
{
this.percentage = value;
this.NotifyOfPropertyChange(() => this.Percentage);
}
}
///
/// Gets or sets PercentageValue.
///
public double PercentageValue
{
get
{
return this.percentageValue;
}
set
{
this.percentageValue = value;
this.NotifyOfPropertyChange(() => this.PercentageValue);
}
}
///
/// Gets or sets StartAt.
///
public int StartAt { get; set; }
///
/// Gets StartPoints.
///
public IEnumerable StartPoints
{
get
{
List startPoints = new List();
for (int i = 1;
i <= this.UserSettingService.GetUserSetting(UserSettingConstants.PreviewScanCount);
i++)
{
startPoints.Add(i);
}
return startPoints;
}
}
///
/// Gets or sets a value indicating whether UseSystemDefaultPlayer.
///
public bool UseSystemDefaultPlayer
{
get
{
return this.useSystemDefaultPlayer;
}
set
{
this.useSystemDefaultPlayer = value;
this.NotifyOfPropertyChange(() => UseSystemDefaultPlayer);
this.userSettingService.SetUserSetting(UserSettingConstants.DefaultPlayer, value);
}
}
///
/// Gets or sets a value indicating whether IsEncoding.
///
public bool IsEncoding
{
get
{
return this.isEncoding;
}
set
{
this.isEncoding = value;
this.CanPlay = !value;
this.NotifyOfPropertyChange(() => this.CanPlay);
this.NotifyOfPropertyChange(() => this.IsEncoding);
}
}
///
/// Gets or sets the Currently Playing / Encoding Filename.
///
public string CurrentlyPlaying { get; set; }
///
/// Gets or sets a value indicating whether can play.
///
public bool CanPlay { get; set; }
#endregion
#region Public Methods
///
/// Close this window.
///
public void Close()
{
this.TryClose();
}
///
/// Handle The Initialisation
///
public override void OnLoad()
{
}
///
/// Encode and play a sample
///
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.",
"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 perview.",
"Error", MessageBoxButton.OK, MessageBoxImage.Error);
return;
}
EncodeTask encodeTask = new EncodeTask(this.Task)
{
PreviewDuration = this.Duration,
PreviewStartAt = this.StartAt,
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.StartAt.ToString(CultureInfo.InvariantCulture);
encodeTask.PreviewEncodeDuration = this.Duration;
QueueTask task = new QueueTask(encodeTask, HBConfigurationFactory.Create(false));
ThreadPool.QueueUserWorkItem(this.CreatePreview, task);
}
#endregion
#region Private Methods
///
/// Play the Encoded file
///
private void PlayFile()
{
// Launch VLC and Play video.
if (this.CurrentlyPlaying != string.Empty)
{
if (File.Exists(this.CurrentlyPlaying))
{
string args = "\"" + this.CurrentlyPlaying + "\"";
if (this.UseSystemDefaultPlayer)
{
Process.Start(args);
}
else
{
if (!File.Exists(UserSettingService.GetUserSetting(UserSettingConstants.VLC_Path)))
{
// Attempt to find VLC if it doesn't exist in the default set location.
string vlcPath;
if (8 == IntPtr.Size || (!String.IsNullOrEmpty(Environment.GetEnvironmentVariable("PROCESSOR_ARCHITEW6432"))))
vlcPath = Environment.GetEnvironmentVariable("ProgramFiles(x86)");
else
vlcPath = Environment.GetEnvironmentVariable("ProgramFiles");
if (!string.IsNullOrEmpty(vlcPath))
{
vlcPath = Path.Combine(vlcPath, "VideoLAN\\VLC\\vlc.exe");
}
if (File.Exists(vlcPath))
{
UserSettingService.SetUserSetting(UserSettingConstants.VLC_Path, vlcPath);
}
else
{
this.errorService.ShowMessageBox("Unable to detect VLC Player. \nPlease make sure VLC is installed and the directory specified in HandBrake's options is correct. (See: \"Tools Menu > Options > Picture Tab\")",
"Error", MessageBoxButton.OK, MessageBoxImage.Warning);
}
}
if (File.Exists(UserSettingService.GetUserSetting(UserSettingConstants.VLC_Path)))
{
ProcessStartInfo vlc = new ProcessStartInfo(UserSettingService.GetUserSetting(UserSettingConstants.VLC_Path), args);
Process.Start(vlc);
}
}
}
else
{
this.errorService.ShowMessageBox("Unable to find the preview file. Either the file was deleted or the encode failed. Check the activity log for details.",
"Error", MessageBoxButton.OK, MessageBoxImage.Warning);
}
}
}
///
/// Create the Preview.
///
///
/// The state.
///
private void CreatePreview(object state)
{
// Make sure we are not already encoding and if we are then display an error.
if (encodeService.IsEncoding)
{
this.errorService.ShowMessageBox("Handbrake is already encoding a video! Only one file can be encoded at any one time.",
"Error", MessageBoxButton.OK, MessageBoxImage.Error);
return;
}
this.encodeService.EncodeCompleted += this.encodeService_EncodeCompleted;
this.encodeService.EncodeStatusChanged += this.encodeService_EncodeStatusChanged;
this.encodeService.Start((QueueTask)state);
this.userSettingService.SetUserSetting(UserSettingConstants.LastPreviewDuration, this.Duration);
}
#endregion
#region Event Handlers
///
/// Handle Encode Progress Events
///
///
/// The sender.
///
///
/// The EncodeProgressEventArgs.
///
private void encodeService_EncodeStatusChanged(object sender, HandBrake.ApplicationServices.EventArgs.EncodeProgressEventArgs e)
{
this.Percentage = string.Format("{0} %", e.PercentComplete.ToString(CultureInfo.InvariantCulture));
this.PercentageValue = e.PercentComplete;
}
///
/// Handle the Encode Completed Event
///
///
/// The sender.
///
///
/// The EncodeCompletedEventArgs.
///
private void encodeService_EncodeCompleted(object sender, HandBrake.ApplicationServices.EventArgs.EncodeCompletedEventArgs e)
{
this.Percentage = "0.00%";
this.PercentageValue = 0;
this.IsEncoding = false;
this.encodeService.EncodeCompleted -= this.encodeService_EncodeCompleted;
this.encodeService.EncodeStatusChanged -= this.encodeService_EncodeStatusChanged;
this.PlayFile();
}
#endregion
}
}